初心者におすすめの具体的なCSS設計手法を紹介!

CSS設計は中級者向けの内容なので、難しいと感じる方も多いでしょう。

確かにいきなり有名な手法を使おうと思っても、『この場合はどうするんだ...?』と迷うことも多いはずです。

弊社が運営している、コーディングの練習が出来るサービス模写修行を制作する際、どんなCSS設計を採用するか悩みました。

模写修行は、ある程度基礎を学び終えたくらいの方が対象なので、有名なCSS設計やそもそもCSS設計自体を知らなくても使えるようにしなければいけません。

この記事では、有名な手法(OOCSS / SMACSS / BEM / … など)の考え方を採用しつつ、webサイトからwebサービスまで、なるべく幅広く対応出来るようなCSS設計手法を紹介します。

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

gakuのアイコン

CSS設計に関して、必須で学ぶべき内容を網羅的に解説した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;
}

シングルクラスの採用

種類説明
シングルクラス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>

使用例(シングルクラスでの書き方)

例えばボタンの上に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に書いたスタイルが適応されているか分かりやすいように基本的にはシングルクラスにしました。

サイトによってはマルチクラスでの運用の方がスッキリ書けて、ページや要素の追加も楽かもしれません。

gakuのアイコン

ディレクトリ構成

ディレクトリ構成は雛形をダウンロードしてもらえると分かりやすいと思います。

小中規模なサイトを制作する想定なので、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カテゴリ

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カテゴリ
リセットCSSとサイト内共通で効かせたいスタイルが入る

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カテゴリ

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カテゴリ

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カテゴリ

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カテゴリ

pageカテゴリ
各ページ固有のコードが入る

class名には各ページの名前を必ず入れます。

ex) serviceページの場合

service-title{…}
service-text{…}
service-button{…}

ex) aboutページの場合

about-title{…}
about-text{…}
about-button{…}

各ページの名前をプレフィックスにしておけば、他のページとclass名が被ることもありません。

コンポーネントが少なく、pageカテゴリのスタイルが1番多くなることも少なくありません。

SCSSで書く場合は、ページ名でディレクトリを切って、その中にページのブロック(塊)ごとにファイル分割することになります。

animationカテゴリ

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設計の知識を網羅的に解説しています。具体的にサイトを作ってみるセクションもあるので、よりイメージが湧くようになっています。

模写修行でも、実践的な練習ができるようになっています。

特に、中級の教材はCSS設計の勉強になるように作りました。解説とコードの配布もあるので、ご自身の書いたコードと比較して勉強することができます。

基礎学習後...迷子になっていませんか?

模写修行やこのメディアを作ったメンバー中心に、Web制作業界を目指す方のための学習支援サービス 『Hello Mentor』 を運営しています。

下記のような、基礎学習後にやるべきことがわからず、迷子状態になっている方に特におすすめです

  • 基礎学習後にやるべきことがわからない...
  • スクール卒だけど実力不足だと感じている...
  • 自分のコードが正しい書き方かわからない...
  • 未経験から1人で転職できる気がしない...
  • 独立するためのノウハウがない...

メンターは、全員が現役のプロです。駆け出しの方やメンターだけをやっている方はいません。

少数精鋭で運営しているため、受け入れ人数に限りがあります。本気でWeb制作業界を目指している方は、ぜひご検討ください。

受け入れ人数制限あり

詳しく見る

サブスクで入会金・解約金・最低契約期間もなし

この記事を書いた人

Gakuのアイコン

Gaku /

フリーランス8年を経て法人化(4期目)。コンテンツ制作、ライティング、マーケティング、デザイン、コーディング、プログラミングなど、幅広くやってます!

Web制作会社が運営する学習支援サービス👉

詳しく見る
模写修行のトップページのスクリーンショット

完全無料のコーディング練習サイト