この節について
前の節で作成したmod-example-0001のソースコードをもとにモジュール作成の最重要ポイントを解説していきます。
あまり細かなことまで挙げすぎるとキリがないので、この節では「とてもやさしいCSS設計」においての土台となる以下の7つの最重要ポイントに焦点を絞って解説していきます。
- 1モジュールにつき1ファイル作成する
- BEMの命名規則に則ってクラス名を決める
- モジュールの幅は固定しない
- 位置調整のプロパティはBlockクラスに設定しない
- Elementクラスの影響範囲はBlock内に絞る
- Modifierクラスは元となるクラスと一緒に付与したときだけスタイルを適用する
- 親セレクタ参照(&)をクラス名の一部として使用しない
1. 1モジュールにつき1ファイル作成する
そのままの意味ですが、ファイルを適切な粒度で分割することはCSSを管理するうえで重要な考え方です。
2. BEMの命名規則に則ってクラス名を決める
一般的に広く知られているBEMの命名規則に則ってクラス名を決めることで、チームに新メンバーを迎えるときも早く慣れてもらうことができ、チームメンバーの誰が見ても各クラスの役割がひと目でわかります。
前の節でも少し触れましたが、この「とてもやさしいCSS設計」で使用するクラスの命名規則は必ず以下の4種類のいずれかに当てはまります。
- Block
- BlockのModifier
- Element
- ElementのModifier
たったの4種類なので、この後の第3章でモジュールを作成していくうちに慣れてくると思います。
3. モジュールの幅は固定しない
モジュールを再利用しやすい状態に保つため、モジュールの幅は以下のどちらかになるようにします。
- 親要素の幅いっぱいに広がる
- 中に入っている文字数などに合わせて広がる
親要素の幅いっぱいに広がるようにするというのは、module-list.htmlをブラウザ開いて、mod-example-0001
を見ていただくとわかると思います。
中に入っている文字数などに合わせて広がるというのは、display:inline-block;
のプロパティを設定したときを想像するとわかりやすいと思います。
モジュールの幅を親要素や中身に委ねることで、幅を変化させるModifierクラスを定義しなくて済むため、コードをシンプルに保つことができ、CSSの管理がしやすくなります。
4. 位置調整のプロパティはBlockクラスに設定しない
表示位置を調整する以下のようなプロパティは、モジュールを再利用しやすい状態に保つため、Blockクラスには設定しません。
4-1. float
4-2. position、top、right、bottom、leftなどによる位置調整
4-3. margin
4-4. z-index
実際には、Blockクラスのmarginは、first-childやnot(:first-child)などの擬似クラスを使用したり、隣接兄弟要素セレクタを使用するなどして、条件付きで設定する方が編集効率の面で効果的な場合が多くありますが、今の段階では最も簡単で覚えやすい方法として「marginはBlockクラスに設定しない」と覚えておいてください。
条件付きでmarginを設定する方法の詳細は後の章で解説していきます。
5. Elementクラスの影響範囲はBlock内に絞る
コンパイル結果であるmodule-list.css
の一部を抜粋した以下のコードを見ていただくとわかりやすいと思います。
1 | .mod-example-0001 .mod-example-0001__first-element { |
mod-example-0001__first-element
クラスは必ず.mod-example-0001
クラスよりも内側のタグに付与しないとスタイルが適用されないようにしています。
その理由については「7. 親セレクタ参照(&)をクラス名の一部として使用しない」で述べます。
6. Modifierクラスは元となるクラスと一緒に付与したときだけスタイルを適用する
コンパイル結果であるmodule-list.css
の一部を抜粋した以下のコードを見ていただくとわかりやすいと思います。
1 | .mod-example-0001.mod-example-0001--danger { |
上記のコードから、BlockクラスとそのModifierクラスが一緒に付与されたときだけスタイルが適用されることがわかります。
以下のコードは、コンパイル結果のうちElementのModifierクラスを抜粋したものです。
1 | .mod-example-0001 .mod-example-0001__list-item.mod-example-0001__list-item--danger { |
こちらもElementクラスとそのModifierクラスが一緒に付与されたときだけスタイルが適用されることがわかります。
Modifierは元となるクラスのプロパティを上書きする役割から、元となるクラスよりも詳細度を少し高くする方がクラスを記述する順番に拘らず確実にプロパティを上書きでき、余計なことに頭を使わなくて済むことが理由のひとつです。
もうひとつの理由は「7. 親セレクタ参照(&)をクラス名の一部として使用しない」で述べます。
CSSの詳細度についてここでは説明しませんが、CSSを書くうえでは非常に重要なことのひとつですので、CSSの詳細度についてまだ知らないという方はWebで検索しておくことをおすすめします。
7. 親セレクタ参照(&)をクラス名の一部として使用しない
これは「5. Elementクラスの影響範囲はBlock内に絞る」と「6. Modifierクラスは元となるクラスと一緒に付与したときだけスタイルを適用する」にも関連していることですが、親セレクタ参照(&)について以下のような使い方をしないということです。
1 | .mod-example-0001 { |
Webページのレイアウトが崩れたときに、ブラウザの開発者ツールを使用して修正対象となるクラスを特定することはよくあると思いますが、例えばmod-example-0001__first-element
のスタイルが原因だとわかったときに、tutorial/srcディレクトリ内を.mod-example-0001__first-element
で検索すると修正対象のコードが素早く見つけられることが1つ目の理由です。
また、&をクラス名の一部として使用したときのコンパイル結果の一部を抜粋すると以下のようになります。
1 | .mod-example-0001 { |
こうなると、例えば文字の色を赤くしたいと思ったときに、どこにあるタグにmod-example-0001__list-item--danger
を付与しても赤くすることができてしまいます。
特に人数の多いチームになると、ほんの少しの軽い気持ちや思い違いでBEMのルールから外れたクラス付与を行ってしまったり、スケジュールが逼迫していることを理由に、BEMのルールの理解が不十分なままの新メンバーを実務にアサインして、Blockよりも外側のタグにクラスが付与されることになってしまい、そのまま長期的な運用をしていくうちに他のメンバーが気付かないところで少しずつ壊れていくケースはこれまでに多く目にしてきました。
このような問題を可能な限り減らすためには、クラスをHTMLに付与する人がBEMのルールを正しく理解しそのルールを守ることはもちろん重要ですが、それよりも前の段階、つまりCSSの書き方によってクラスの影響範囲をチームが意図したBlock内に制限することを重要視しています。
これによってBlock外のタグへの誤ったクラス付与を防ぐことができ、CSSを編集するときには想定外の箇所への影響を起り難くし、長期的にメンテナンスしやすいCSSになるようにしています。
少し説明が長くなりましたが、これが2つ目の理由です。
とてもやさしいCSS設計では、セレクタ毎の影響範囲を把握しやすくするために特にこの2つ目の理由は重要視しており、最重要ポイントとして「5. Elementクラスの影響範囲はBlock内に絞る」と「6. Modifierクラスは元となるクラスと一緒に付与したときだけスタイルを適用する」を挙げています。
この節のおわりに
この節で挙げた7つの最重要ポイントを守ってさえいれば、SCSSのコードがどんなに煩雑になったとしても、影響はBlock内だけに留められますし、設計に失敗したモジュールだけを捨てて差し替えることもしやすいため、CSSは格段に管理しやすくなります。
ぜひこの最重要ポイントを繰り返し読んで、しっかりと理解していただけたらと思います。
とはいえ、これではまだ土台だけであり、実際にページを完成させるまでの具体的な方法や、後で困らないmarginの設定の仕方など、まだ説明できていないこともありますので、もっと多くのモジュールやページの作成を通して、具体的に説明していこうと思います。