弊社で作った教材がセール中!
CSS設計は中級者向けの内容なので、難しいと感じる方も多いでしょう。
確かにいきなり有名な手法を使おうと思っても、『この場合はどうするんだ...?』と迷うことも多いはずです。
弊社が運営している、コーディングの練習が出来るサービス模写修行を制作する際、どんなCSS設計を採用するか悩みました。
模写修行は、ある程度基礎を学び終えたくらいの方が対象なので、有名なCSS設計やそもそもCSS設計自体を知らなくても使えるようにしなければいけません。
この記事では、有名な手法(OOCSS / SMACSS / BEM / … など)の考え方を採用しつつ、webサイトからwebサービスまで、なるべく幅広く対応出来るようなCSS設計手法を紹介します。
CSS設計に関して、必須で学ぶべき内容を網羅的に解説したUdemy教材を出しました。具体的にサイトを作ってみるセクションもあるので、よりイメージが湧くと思います。
【セール中】弊社で出したUdemy教材
書籍や記事で学びたい方は、下記の記事もご覧ください。
ざっくり学ぶCSS設計入門 【レビュー記事】CSS設計に関するおすすめの本はこの3冊で決まり!👇 メンターやってます 👇
模写修行やこのメディアを作ったメンバー中心に、Web制作業界を目指す方のための学習支援サービス 『Hello Mentor』 を運営しています。
基礎学習後に迷子になっていませんか?脱初心者したいなら、私たちにお任せください!
特にこんな方におすすめ!
- 基礎学習後にやるべきことがわからない...
- スクール卒だけど実力不足だと感じている...
- 自分のコードが正しい書き方かわからない...
- 未経験から1人で転職できる気がしない...
- 独立するためのノウハウがない...
まずは、下記リンクから個別ガイダンスへお越しください。
👆 メンターやってます 👆
この記事の目次
雛形コードのダウンロード
雛形コードを見ながらこの記事を読んだ方が、より理解できると思います。どこに何を書くか、イメージがつくようにコメントを入れただけの雛形です。
SCSSを使わない方は、下記のファイルは消してしまって大丈夫です。
- scssディレクトリ内全て
- css > style.css.map
SCSSはDart Sassを使うことを前提にしています。VSCodeの拡張機能を使って、Dart Sassをコンパイルする方法は、下記の記事を参考にしてみてください。
Dart SassをVSCodeの拡張機能(プラグイン)で利用する方法を紹介コーディングする際の基本ルール
ガチガチのルールを設けるわけではなく、最低限にとどめています。重要な点だけ抑えて、それ以外の細かい点は好みもあるので自分の中でルール化すれば良いです。
classの命名
class名は全てハイフン区切りにしています。
.service-title{...}
.service-list{...}
.service-item{...}
.c-button {...}
.c-button--primary {...}
.c-button--secondary {...}
.c-button--accent {...}
カラーやサイズなどのバリエーションを実装するための、バリエーションクラス(Modifier)はハイフンを2つつけるルールにしています。下記が使用例です。
<!-- 背景赤色のボタンになる -->
<button class="c-button c-button--accent">ボタン</button>
.c-button { /* 全ボタンに適応させたいスタイルを書く */ }
.c-button--primary {
background-color: #000;
color: #fff;
}
...
.c-button--accent {
background-color: red;
color: #fff;
}
- class名の省略はなるべくしない
- 連番が必要な場合は、1番目は番号は付けずに、2番目から付ける
シングルクラスの採用
| 種類 | 説明 |
|---|---|
| シングルクラス | 1つのタグに1つのclassがつく |
| マルチクラス | 1つのタグに複数のclassがつく |
シングルクラスとマルチクラスの定義はこのようにしています。基本的にはシングルクラスで書きますが、例外もありにします。
例外(マルチクラスになる例)
<!-- 🙆♂️ OK -->
<h2 class="c-title c-title—-center">
Modifierと一緒に使うケースはOK
</h2>
<!-- 🙆♂️ OK -->
<div class="service u-ptb-m">
utilityと一緒に使うケースはOK
</div>
<!-- 🙆♂️ OK -->
<section class="service l-section">
layoutと一緒に使うケースはOK
</section>
<!-- 🙅♂️ NG -->
<section class="service-title c-title">
componentと一緒に使うケースはNG
</section>
<!-- 🙆♂️ OK -->
<h2 class="c-title c-title—-center js-page-title has-animation-title-fade-in is-title-fade-in-active">
JavaScriptで操作する際にこのようになるケースもOK
</h2>
- Modifierと一緒に使うケース
- utilityと一緒に使うケース
- layoutと一緒に使うケース
- componentと一緒に使うケース
- JavaScriptのフックを使用するケース
- アニメーションを使用するケース
- 状態によってJavaScriptで追加削除されるケース
使用例(シングルクラスでの書き方)
例えばボタンの上に40pxの余白を開けたい場合は、下記のように書きます。.c-buttonは色々なところで使い回すパーツ(コンポーネント)です。
<!-- 🙅♂️ NG -->
<button class="c-button contact-submit-button">…</button>
<!-- 🙆♂️ OK -->
<div class="contact-submit-button">
<button class=“c-button>…</button>
</div>
.contact-submit-button{
margin-top: 40px;
}
NGの例は悪い書き方というわけではありません。今回はそのような書き方をしないルールにしただけです。どのclassに書いたスタイルが適応されているか分かりやすいように基本的にはシングルクラスにしました。
サイトによってはマルチクラスでの運用の方がスッキリ書けて、ページや要素の追加も楽かもしれません。
ディレクトリ構成
ディレクトリ構成は雛形をダウンロードしてもらえると分かりやすいと思います。
小中規模なサイトを制作する想定なので、CSSは1ファイルにコメントで区切りながら書きます。SCSSの場合は、後述する役割ごとにディレクトリを切って、その中でブロックごとに分割しています。
ブロックとはそのサイトやページの中でのパーツや塊だと思ってもらえればOKです。
その他
基本的にスタイリングする際はclassを付与して、単体のclassセレクタに書きます。
/* 🙅♂️ NG */
.hoge h2{
margin-top: 40px;
}
/* 🙆♂️ OK */
.hoge-title{
margin-top: 40px;
}
/* 🙆♂️ 例外でOK */
.c-posts--col3 > .c-posts-item{
...
}
基礎学習後...迷子になっていませんか?
Web制作業界を目指す方の多くが、基礎学習後にやるべきことがわからず、迷子状態になっています。あなたも下記のように感じていませんか?
- 基礎学習後にやるべきことがわからない...
- スクール卒だけど実力不足だと感じている...
- 自分のコードが正しい書き方かわからない...
- 未経験から1人で転職できる気がしない...
- 独立するためのノウハウがない...
そんな悩みを解決するために、模写修行やこのメディアを作ったエンジニア・デザイナー中心に、学習支援サービス 『Hello Mentor』 を運営しています。
転職成功者や副業・フリーランスデビューした方も出ています。
classのカテゴリ分類とその詳細
| classのカテゴリ | 役割 |
|---|---|
| global | サイト内共通の設定 |
| foundation | リセットCSSとサイト内共通で効かせたいスタイル |
| utility | ちょっとした使いわますスタイル |
| component | サイト内で使い回すパーツのスタイル |
| layout | レイアウトを作るスタイル |
| page | 各ページ固有のスタイル |
| animation | アニメーションに関するスタイル |
スタイルをこれらの7つのカテゴリに分類します。これ以降、どんな役割のスタイルか詳しく紹介します。
このような分け方をしたのはDart Sassとの兼ね合いもあります。構成を考える際に参考になった記事を載せておきます。
globalカテゴリ
下記の値をカスタムプロパティで定義しておきます。SCSSを使う場合は、それぞれ別ファイルに書くので4ファイルできることになります。
- カラー
- コンテナの幅
- フォント
- z-index
SCSSを使う場合は、下記の2つもglobalカテゴリに存在します。あまりmixinを使わないので、1ファイルにまとめて書きますが、よく使う場合はmixinディレクトリを作っても良いかもしれません。
- ブレークポイントの設定
- mixin
CSSの場合(SCSSを使わない場合)
/*!
global > color
------------------------------
*/
:root {
--color-font-base: #333;
}
/*!
global > content-width
------------------------------
*/
:root {
--width-content-s: 920px;
--width-content: 1080px;
}
/*!
global > font
------------------------------
*/
:root {
--font-family-base: "Helvetica Neue", Arial, "Hiragino Kaku Gothic ProN", "Hiragino Sans", Meiryo, sans-serif;
}
/*!
global > z-index
------------------------------
*/
:root {
--z-index-modal: 100;
--z-index-header: 30;
--z-index-menu: 10;
--z-index-default: 1;
}
このようにコメントで区切って入れています。
SCSSの場合
ex) _color.scssの内容
/*!
global > color
------------------------------
*/
:root {
--color-font-base: #333;
}
ex) _breakpoints.scssの内容
@use "sass:map";
// global > breakpoint
// ------------------------------
$breakpoints: (
"sm": 500px,
"md": 768px,
"lg": 1080px,
"xl": 1200px,
);
@mixin mq($breakpoint: md) {
@media screen and (min-width: #{map-get($breakpoints, $breakpoint)}) {
@content;
}
}
ex) _mixin_.scssの内容
// 矢印
@mixin arrow($color: var(--baseFontColor), $rotate: 45deg, $w: 6px, $h: 6px, $left: 0, $right: auto) {
position: relative;
&::before {
content: "";
position: absolute;
top: 0;
bottom: 0;
margin: auto;
left: $left;
right: $right;
width: $w;
height: $h;
border-top: 2px solid $color;
border-right: 2px solid $color;
transform: rotate($rotate);
}
}
...
foundationカテゴリ
foundationカテゴリ内はresetとbaseに分類します。分類の基準は下記の通りです。
| 分類 | 役割 |
|---|---|
| foundation > reset | リセットCSS |
| foundation > base | プロジェクト固有のサイト内共通で効かせたいスタイル |
/*!
foundation > reset
------------------------------
*/
html {
color: #000;
background: #fff;
}
body,
div,
dl,
dt,
dd,
ul,
ol,
li,
h1,
h2,
h3,
h4,
h5,
h6,
pre,
code,
form,
fieldset,
legend,
input,
textarea,
p,
blockquote,
th,
td {
margin: 0;
padding: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
width: 100%;
}
fieldset,
img {
border: 0;
}
address,
caption,
cite,
code,
dfn,
em,
strong,
th,
var {
font-style: normal;
font-weight: normal;
}
ol,
ul {
list-style: none;
}
caption,
th {
text-align: left;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: 100%;
font-weight: normal;
}
q:before,
q:after {
content: "";
}
abbr,
acronym {
border: 0;
font-variant: normal;
}
sup {
vertical-align: text-top;
}
sub {
vertical-align: text-bottom;
}
input,
textarea,
select,
button {
color: inherit;
font-family: inherit;
font-size: inherit;
font-weight: inherit;
line-height: inherit;
*font-size: 100%;
border-radius: 0;
border: none;
appearance: none;
-webkit-appearance: none;
background-color: inherit;
}
input,
textarea,
select {
font-size: 16px;
}
textarea {
resize: vertical;
display: block;
}
button {
padding: 0;
cursor: pointer;
}
legend {
color: #000;
}
main {
display: block;
}
a {
text-decoration: none;
color: inherit;
}
img {
width: 100%;
height: auto;
vertical-align: bottom;
}
svg {
display: block;
}
* {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
box-sizing: border-box;
}
*::before,
*::after {
box-sizing: border-box;
}
/*!
foundation > base
------------------------------
*/
body {
line-height: 1.8;
font-size: 14px;
color: var(--color-font-base);
font-family: var(--font-family-base);
}
@media screen and (min-width: 768px) {
body {
font-size: 16px;
}
}
SCSSではfoundationディレクトリの中に、_reset.scssと_base.scssが入ることになります。
utilityカテゴリ
例えば、下記のコードなど、必要最低限にします。class名にはプレフィックスとしてu-を付けるようにします。
- 表示切り替え用のクラス
- 余白関連
- 隠しテキスト
プレフィックスをつけることで、他の箇所でも使っていることを念頭に置きながらコードを書けます。これで思わぬとこに影響してしまうようなリスクも減らせます。
/*!
utility > utility
------------------------------
*/
@media screen and (min-width: 768px) {
.u-sp {
display: none !important;
}
}
.u-pc {
display: none !important;
}
@media screen and (min-width: 768px) {
.u-pc {
display: block !important;
}
}
.u-visually-hidden {
position: absolute !important;
white-space: nowrap !important;
width: 1px !important;
height: 1px !important;
overflow: hidden !important;
border: 0 !important;
padding: 0 !important;
clip: rect(0 0 0 0) !important;
clip-path: inset(50%) !important;
margin: -1px !important;
}
utilityカテゴリは最優先で効いて欲しいので!importantを付けます。!importantをさらに上書きする必要があるケースは、そもそもutility classを使うべきでない箇所なので、上書きに上書きを重ねることはありません。
utilityカテゴリ内のコードはあまり増やさないようにしているので、SCSSの場合は、_utility.scssの1ファイルに全て書きます。
componentカテゴリ
class名にはプレフィックスとしてc-を付けるようにします。
/*!
component > button
------------------------------
*/
.c-button {
...
}
.c-button--primary {
...
}
/*!
component > title
------------------------------
*/
.c-title {
...
}
.c-title--center {
...
}
SCSSではコンポーネントごとにファイル分割します。上の例だと、_button.scssと_title.scssで2つのファイルに分割します。
デザインのルールがしっかり決まっているサイトでは、componentに属するスタイルが多くなります。
layoutカテゴリ
例えば、下記がレイアウトを作るためのスタイルです。
- header
- footer
- sidebar
- container
header / footer / sidebarはレイアウトと分りやすいので、プレフィックスは付けませんが、それ以外には基本的にプレフィックスを付けます。
/*!
layout > container
------------------------------
*/
.l-container, .l-container-s {
width: 90%;
margin: 0 auto;
}
.l-container-s {
max-width: var(--width-content-s);
}
.l-container {
max-width: var(--width-content);
}
/*!
layout > header > header
------------------------------
*/
.header { ... }
/*!
layout > header > header-nav
------------------------------
*/
.header-nav { ... }
/*!
layout > footer > footer
------------------------------
*/
.footer { ... }
/*!
layout > footer > footer-nav
------------------------------
*/
.header-nav { ... }
SCSSではファイル分割します。上の例だと5つのファイルに分割します。シンプルなデザインではheaderやfooterは1ファイルにまとめてしまうこともあります。その辺りは臨機応変に対応します。
pageカテゴリ
class名には各ページの名前を必ず入れます。
ex) serviceページの場合
service-title{…}
service-text{…}
service-button{…}
ex) aboutページの場合
about-title{…}
about-text{…}
about-button{…}
各ページの名前をプレフィックスにしておけば、他のページとclass名が被ることもありません。
コンポーネントが少なく、pageカテゴリのスタイルが1番多くなることも少なくありません。
SCSSで書く場合は、ページ名でディレクトリを切って、その中にページのブロック(塊)ごとにファイル分割することになります。
animationカテゴリ
演出目的とは、例えばスクロールに連動してフェードインさせるようなアニメーションなどのことです。
下記のような演出目的ではなく、機能目的のUIを実装する際は、animationカテゴリに入れません。
- タブメニュー
- モーダル
- ハンバーガーメニュー
アニメーションでの使用例
タイトルが表示領域に入ると、透明度を0から1にアニメーションをするためのサンプルです。
<h2 class="service-title js-page-title has-animation-title-fade-in">
サービス
</h2>
/* SCSSで書く場合のディレクトリは、 */
/* page > service > service.scss */
/* ----------------------------- */
.service-title{
...
}
/* SCSSで書く場合のディレクトリは、 */
/* animation > title-animation.scss */
/* ----------------------------- */
.has-animation-title-fade-in{
opacity: 0;
transition: opacity .3s;
}
.is-animation-title-fade-in-active{
opacity: 1;
}
見た目のスタイルとアニメーションのためのスタイルは分離した方が分かりやすいので、このようにしています。
.js-hogeはJavaScriptのフックに使うもので、このclassに対してスタイリングしてはいけません。
ハンバーガーメニューでの使用例(animation カテゴリに属さない)
<div class="header-menu js-header-menu">
...
</div>
/* SCSSで書く場合のディレクトリは、 */
/* layout > header > header-menu.scss */
/* ----------------------------- */
.header-menu{
...
display: none;
}
/* ハンバーガーメニューactive時に付与するclass */
/* layout > header > header-menu.scss */
.is-header-menu-active{
display: block;
}
このような場合、animationカテゴリには属さず、.header-menuの近くにコメントをつけて書きます。
CSS設計を深く学びたいならUdemy教材で!
弊社で出している下記のUdemy教材では、必須で学ぶべきCSS設計の知識を網羅的に解説しています。具体的にサイトを作ってみるセクションもあるので、よりイメージが湧くようになっています。
【セール中】弊社で出したUdemy教材
模写修行でも、実践的な練習ができるようになっています。
特に、中級の教材はCSS設計の勉強になるように作りました。解説とコードの配布もあるので、ご自身の書いたコードと比較して勉強することができます。
基礎学習後...迷子になっていませんか?
模写修行やこのメディアを作ったメンバー中心に、Web制作業界を目指す方のための学習支援サービス 『Hello Mentor』 を運営しています。
下記のような、基礎学習後にやるべきことがわからず、迷子状態になっている方に特におすすめです
- 基礎学習後にやるべきことがわからない...
- スクール卒だけど実力不足だと感じている...
- 自分のコードが正しい書き方かわからない...
- 未経験から1人で転職できる気がしない...
- 独立するためのノウハウがない...
メンターは、全員が現役のプロです。駆け出しの方やメンターだけをやっている方はいません。
少数精鋭で運営しているため、受け入れ人数に限りがあります。本気でWeb制作業界を目指している方は、ぜひご検討ください。
弊社で作った教材がセール中!
Web制作会社が運営する学習支援サービス👉
詳しく見る


どんなCSS設計を採用するかに正解は無いので、『模写修行流』ということで、1つのサンプルとして参考になれば幸いです。