【初心者向け】綺麗で高品質なCSSの書き方9つのルール

Webサイトは作って終わりではなく、その後も運営・更新していくものなので、他の作業者がコードを見ても理解できるかどうかは非常に重要です。

特にCSSは他の言語と比べて自由に書ける上、記述量も膨大になりやすいので、意識せずにコードを書いているとごちゃごちゃになって管理しきれなくなります。

そのため、誰が見ても読みやすくメンテナンスしやすいコードを書けるコーダーは非常に重宝されます。
また、自身の作業効率も大幅にアップするので、より短時間で仕事をこなせるようになるでしょう。

この記事ではCSS初心者の方に向けて、CSSを綺麗に書くための9つのルールを紹介します。

「ルール」という表現をしていますが、CSSの書き方に絶対的な規約があるわけではありません。
どんな方法でコードを書くのがベストかは、個人や制作チームによって考えが異なるものです。
この記事はあくまで、CSSを綺麗に書くための考え方を”提案”するものになります。

目次

クラス名の付け方はBEMの命名規則に従う

クラス名の付け方に特にこだわりがない場合、BEMの命名規則に従うことを推奨します。

BEMはCSS設計手法の一つで、個人によって書き方がバラバラなCSSに、秩序や統一性を持たせるのに効果的です。
また、知名度がかなり高い命名規則でもあるので、BEMで書いたコードは多くの人が理解しやすいでしょう。

以下、BEMについて簡単な解説を行いますが、さらに詳しく知りたい方はこちらのドキュメントを参考にしてください。

BEMの命名規則では、HTML要素を以下の3つの要素に分類します。

  • Block:独立した意味を持つ要素
  • Element:Block要素の子要素(Block要素を構成する部品の一つ)
  • Modifier:Block要素またはElement要素の状態を表す修飾子

BEMの命名規則に従って書いたHTMLコードの例です。

<header class="header">
    <div class="header__logo-wrapper">
        <img class="header__logo" src="logo.png" alt="" />
    </div>
    <nav class="header__nav">
        <a class="header__button--black" href="#">ボタン1</a>
        <a class="header__button--white" href="#">ボタン2</a>
    </nav>
</header>

上記のコードにおいて、headerクラスは独立した意味を持つBlock要素に当てはまります。

このBlock要素であるheaderを構成する部品の一つ一つ(header__logo-wrapperheader__logoなど)がElement要素になります。Block名に続けてアンダースコア2つ(__)で繋げて命名します。

header__button--blackheader__button--whiteにおける--black, --whiteModifierに相当し、同じ要素の色違いなど、要素の別パターンを表現するために使用されます。Block名またはElement名に続けてハイフン2つ(--)で繋げて命名します。

BEMの命名規則を使うことで、HTMLファイルを見ただけで各要素の構造がわかりやすくなります。
また、親要素であるBlockの名付け方に気を遣っていれば、意図しないクラス名の重複が発生しにくくなるメリットもあります。

この記事ではBEMをピックアップしましたが、それ以外でも何かしらのCSS設計手法を取り入れていれば、CSSは格段に見やすく・管理しやすくなります。

CSS設計についてさらに学びたい方は、以下の書籍がとても参考になります。
これ1冊でCSS設計を完全マスターできるので、よりハイレベルなコーダーになれること間違いなしです。

意味を予測しやすいクラス名をつける

誰が見ても理解しやすいCSSを書くためには、意味を予測しやすいクラス名をつける事が重要です。

クラス名の付け方には明確な正解があるわけではありませんが、以下の2つのポイントを押さえることで、予測しやすいクラス名を付けやすくなります。

  • クラス名からその要素の機能・構造がわかる
  • 英単語を無理やり省略しない

クラス名からその要素の機能・構造がわかる

悪い例:

<div class="item">
    <div class="top">
        <img class="image" src="sample.jpg" alt="" />
    </div>
    <div class="bottom">
        <h2 class="big-text">タイトル</h2>
        <p class="text">本文が入ります。本文が入ります。</p>
    </div>
</div>

「悪い例」では、親要素のitemというクラス名は大雑把すぎてどんな要素なのか予測できません。
また、top, image, text等のクラス名は、item以外の他の要素にも使える名前なので、itemクラスの中身を指定したものなのか、共通するクラスの指定なのかが分かりづらくなっています。

良い例:

<div class="card">
    <div class="card__image-wrapper">
        <img class="card__image" src="sample.jpg" alt="" />
    </div>
    <div class="card__body">
        <h2 class="card__title">タイトル</h2>
        <p class="card__text">本文が入ります。本文が入ります。</p>
    </div>
</div>

「良い例」では、親要素のcardというクラス名から、カード型のパーツであることが予測できます。
また、カードを構成する要素にはBEMの命名規則に則ったクラス名が付けられており、card__imageならカードの画像、card__titleならカードのタイトルを表していることが、クラス名を見るだけで予測できます。

上記のように、クラス名は、その要素の機能・構造が瞬時に理解できるように付けましょう。

クラス名をつける際のヒントとして、CSSでよく使用される英単語が以下の記事によくまとめられているので、参考にしてみてください。
CSSのクラス名を決めるときに使うリストをつくりました(外部サイト)

英単語を無理やり省略しない

悪い例:

.sec-ab {

}

良い例:

.section-about {

}

「悪い例」では、secがsectionの省略形、abがaboutの省略形であることは、一見しただけでは理解できません。
クラス名が多少長くなってでも、英単語を無理に省略することは避けるべきです。

ただし、以下のように省略形で使用されることが一般的な単語については、省略しても問題ないでしょう。

  • image → img
  • column → col
  • first view → fv
  • previous → prev
  • navigation → nav
  • background → bg
  • information → info

CSSセレクタの階層は最小限に抑える

管理しやすいCSSを書くためには、詳細度を不必要に上げないことが重要になります。

CSSの詳細度とは、同じ要素に複数のスタイル指定が適用される際に、どの指定が優先されるかを決定するための仕組みです。セレクタを特定するための指定が詳細であるほど、詳細度は高くなります。

例えば、以下のようなコードがあるとします。

<header class="header">
    <button class="button">ボタン</button>
</header>
.header .button {
    color: red; /* ○適用される */
}

.button {
    color: green; /* ×適用されない */
}

この場合、CSSにおいてセレクタ名をより詳細に指定している一番上の記述が最も高い詳細度となり、color: redが適用されます。

このように、階層が深いCSSセレクタが含まれていると、「後からスタイルを上書きしているのに反映されない」といった状況が発生しやすくなります。正確には、元の詳細度以上でスタイル指定すれば上書きできますが、元の詳細度を一々確認する必要が出てくるので、メンテナンス性は低下してしまうでしょう。

詳細度を計算しなくていい(気にする必要がない)CSSが理想形です。

必要がない限り、セレクタの指定は1階層で(子要素化せずに)記述するのがベストです。

同時にBEMの命名規則を使うことで、クラス名が重複するリスクも低減できます。
先程の例で言えば、buttonというクラス名はヘッダー以外の他の箇所でも使用される可能性があるため、header内の子要素である事がわかるよう、header__buttonというクラス名が適しています。

.header__button {
    color: red;
}

上記のようにBEMの命名規則を使う事で、セレクタの指定を1階層で記述しながら、クラス名の意図しない重複を避ける事ができます。

classに対してのみスタイルを当てる

CSSでスタイルを当てることができる要素は、大まかに以下の3つになります。

  • class
  • id
  • タグ
/* classにスタイルを当てる例 */
.about {
    color: #000;
}

/* idにスタイルを当てる例(非推奨) */
#about {
    color: #000;
}

/* タグにスタイルを当てる例(原則、非推奨) */
p {
    color: #000
}

管理しやすいコードを書くためには、原則、classに対してのみスタイルを当てるべきです。
その理由を以下で解説していきます。

idにスタイルを当てない

idに対してスタイルを当てることは、詳細度を最も上げる指定方法になります。

例えば、以下のようなコードがあるとします。

<header class="header">
    <button id="button" class="button">ボタン</button>
</header>
#button {
    color: red; /* ○適用される */
}

html body .header .button {
    color: green; /* ×適用されない */
}

一見すると、CSSの後半の記述の方がセレクタ階層が深く、詳細度が高そうに見えますが、
idに対する指定は詳細度を最も上げるため、適用されるのは前半に記述していたcolor: redとなります。

idに対するスタイル指定は、詳細度の計算を一気にややこしくするため、避けましょう。

タグに直接スタイルを当てない(原則)

「タグに直接スタイルを当てる」とは、例えば以下のような記述です。

<h2 class="title">見出し<h2>
h2 {
    color: red;
}

このような記述方法は、他のh2要素全てに対してもスタイルが適用されてしまうため、原則避けるべきです。
タグではなく、classに対してスタイルを指定しましょう。

classにスタイル指定することで、後にタグが変更された場合にCSSの記述を変更せずに済むメリットもあります。

<h2 class="title">見出し<h2>
.title {
    color: red;
}

上記のように、classに対してスタイルを当てることで、<h2>要素が例え<h3>や<h4>に変わったとしても、CSSの記述は変更する必要がありません。

尚、タグに直接スタイルを当てるのを原則避けるべきと書いたのは、リセットCSSを使う場合と、CMS化する場合を考慮してです。
リセットCSSはブラウザ固有のデフォルトのスタイルを打ち消すために必須なものなので、リセットCSS内でタグに直接スタイルを当てていることは問題ありません。
CMS化する場合は、システムで生成されたHTML要素にclassが付いていないこともあるので、時としてタグに直接スタイルを当てる必要性が出てくるでしょう。

class名の前のタグ名は不要

他の方のコードや解説記事を見ていると、時折以下のようなコードを目にします。

p.message {
    color: #fff;
}

上記で言えば、.messageクラスの前のpタグの指定は無くてもスタイルは適用されます。

もしも、同じクラスを持つ<p>タグと<span>タグでスタイルを分けたいというような場合は、そもそも両者に別のクラスをつければ済む話です。

悪い例:

p.message {
    color: #fff;
}

span.message {
    color: red;
}

良い例:

.message {
    color: #fff;
}

.color-red {
    color: red;
}

class名とタグ名の複合は、する必要がない上にCSSの詳細度を無駄に上げてしまうので、避けましょう。

!importantは原則使用しない

!importantを使用すると、通常のCSSの詳細度のルールを無視して、スタイルが強制的に適用されます。

.button {
    color: red !important; /* ○適用される */
}

html body #header .inner .button {
    color: green; /* ×適用されない */
}

上記の例では、!importantが使用されたスタイルが存在することで、後半のコードの詳細度の高さは無視され、強制的にcolor: redが適用されます。

!importantが使用されたスタイルを上書きするには、同じく!importantを指定するしかありません。
そのため、安易に!importantを使ってしまうと、CSSが!importantだらけになってしまい、メンテナンス性が著しく低下します。

!importantは原則使用しないように徹底しましょう。
(CSSフレームワークや、外部のライブラリなどのスタイルを打ち消すために、やむを得ず使用しなければならない場合はあります。)

Bootstrapは原則使用しない

何かと初心者に人気なイメージのあるBootstrapですが、Bootstrapの使用が適している案件って正直ほとんど無いと思っています。

結論、Bootstrap等のCSSフレームワークを使用するのは、以下の条件に当てはまる場合に限定するべきです。

  • CSSフレームワークの使用を前提としてデザイン制作された案件
  • デザインはないが、とりあえず見た目だけは綺麗にしておきたい(管理画面など)案件
  • CSSフレームワークの機能だけでコーディングを完結できる(自前でCSSを書く必要がない)案件

コーダーが担当する大半の案件では、デザインにオリジナリティが求められ、CSSフレームワーク側で用意されたスタイルだけでコーディングを完結できるケースはほぼありません。

そのような案件にBootstrapを取り入れようとしたら、必ずBootstrapのデフォルトのスタイルを上書きするためのコードが大量に必要になってきます。

自前でCSSを書かずに実装できるというCSSフレームワークの最大のメリットを享受できないだけでなく、フレームワークのスタイルと独自のスタイルが乱立することで、コードの可読性・メンテナンス性も非常に悪化します。

クライアントから指示がない限り、Bootstrapは封印することを強く推奨します。

Bootstrapは非推奨としましたが、その他のCSSフレームワークの一つ「Tailwind CSS」は非常に使いやすく、おすすめです。JITモードを使用することで自前のCSSを書く必要がほぼなくなり、クラス名やCSS設計を考える時間を削減できます。とはいえ、環境構築が必要でWeb開発の分野では人気がありますが、Web制作の領域ではあまり使用されていないため、使い所は選ぶべきでしょう。

SCSSの&(アンパサンド)は極力使わない

例えば、以下のようなHTML要素があるとします。

<header class="header">
    <img class="header__logo" src="logo.png" alt="">
    <h1 class="header__title">タイトル</h1>
    <button class="header__button">ボタン</button>
</header>

この要素にスタイルを当てる際、SCSSの場合、&(アンパサンド)を使う事で以下のように記述できます。

.header {
    height: 80px;

    &__logo {
        width: 320px;
    }

    &__title {
        font-size: 2rem;
    }

    &__button {
        background-color: #333;
    }
}

このような記述方法はコードの記述量を少なくできるメリットはありますが、以下のデメリットの方が大きいため使用を控えた方が良いです。

  • 行数が増えると、&がどの要素と連結しているか分かりづらくなる
  • クラス名でコード内検索した際、検索結果に表示されなくなる

少し冗長になってでも、以下のように記述するのがベストです。

.header {
    height: 80px;
}

.header__logo {
    width: 320px;
}

.header__title {
    font-size: 2rem;
}

.header__button {
    background-color: #333;
}

ただし、:hoverなどの擬似クラスについては、&(アンパサンド)を使用しても特に問題はないでしょう。

.header__button {
    background-color: #333;

    &:hover {
        background-color: #fff;
    }
}

JavaScript用とCSS用のクラスを区別する

基本的に、JavaScriptでHTML要素を指定する際は、id属性で要素を取得する事が推奨されています。
(idはページ内で唯一の存在であるため、要素の取得の実行速度が速い)

しかし、場合によっては複数の要素に処理を行いたい場合など、クラス名での指定が必要なケースもあります。
その場合、js-で始まるクラス名を追加し、CSSで使用するクラスと明確に区別すると良いです。

<button class="tab js-tab">タブ1</button>
<button class="tab js-tab">タブ2</button>
<button class="tab js-tab">タブ3</button>

上記の例では、CSSに関する記述はtabクラスに対してのみ、JavaScriptに関する記述はjs-tabクラスに対してのみ行うようにします。

このようにする事で、後にCSS用のクラス名を変更した際に、予期せずJavaScriptが動かなくなってしまう不具合を回避することができます。(逆もまた然り)

Prettier(コードフォーマッター)を導入する

Prettierは、ソースコードを自動的に見やすく整形してくれるコードフォーマッターです。

こんなにぐちゃぐちゃになったコードでも・・・

インデントや改行位置がバラバラになったコードの例

ファイルを保存するだけで一瞬でコードが整形され、見やすくなります。

Prettierにより見やすく整形されたコードの例

このような、コードを見やすくするための整形は、一々手作業で行うのは非効率な上、人為的ミスも起きやすいので、ツールで自動化してしまうことをおすすめします。

Prettierを使用するための方法は色々ありますが、VSCodeの拡張機能「Prettier – Code formatter」を使うことで、VSCodeで簡単にPrettierの機能を使うことが出来ます。

インストールや設定方法については以下の記事で詳しく解説しています。

まとめ:これが出来ればCSS中級者

綺麗で高品質なCSSを書くためのルールを9つ紹介しました。

今回の記事のまとめです。

  • クラス名の付け方はBEMの命名規則に従う
  • 意味を予測しやすいクラス名をつける
  • CSSセレクタの階層は最小限に抑える
  • classに対してのみスタイルを当てる
  • !importantは原則使用しない
  • Bootstrapは原則使用しない
  • SCSSの&(アンパサンド)は極力使わない
  • JavaScript用とCSS用のクラスを区別する
  • Prettier(コードフォーマッター)を導入する

今まで特に意識せずコードを書いていた方にとっては、この記事の内容を守るだけで格段に見やすく管理しやすいCSSを書けるようになるはずです。

内容が良かったらSNSでシェアしていただけると嬉しいです!
目次