「CSS設計のキホンと王道パターン(前半)」を聞いた雑メモ
「CSS設計」の話題については、設計手法の名前(BEM, OOCSS, ……)が色々登場するややこしそうな話題、というイメージがあってとっつきにくさを感じていたんですが、Youtubeで見つけたこの動画の中の「CSS設計 8つのポイント」という話が入口として良さそうだったのでメモを残しておきます。
【前半】『CSS設計完全ガイド』の著者による「CSS設計のキホンと王道パターン」/半田 惇志(100/パンセ)
CSS設計完全ガイドという本を書いている方による、オンライン勉強会での発表の録画動画です。本も読んでみよう。
CSS設計 8つのポイント
動画ではCSS設計で考えるべきポイントを8つ紹介しています。
- 特性に応じてCSSを分類する
- HTMLとスタイリングが疎結合である
- 影響範囲がみだりに広すぎない
- 特定のコンテキストにみだりに依存していない
- 詳細度がみだりに高くない
- クラス名から影響範囲が想像できる
- クラス名から見た目・機能・役割が想像できる
- 拡張しやすい
これらは各設計手法に共通する考え方とのこと。まずはこれらのポイントを押さえた上で、各手法を学ぶのが良さそう。
特性に応じてCSSを分類する
コードの役割・責任を明確にし、整理する。
分類の例:
- リセットCSSやサイト全体に適用するスタイル→「ベースグループ」
- ヘッダーやフッター、コンテンツエリアなど特定のエリアに適用するスタイル→「レイアウトグループ」
- 設計手法によっては
l-とかly_とか接頭辞を付ける
- 設計手法によっては
- モジュール(再利用可能な要素)に関わるスタイル →「モジュールグループ」
HTMLタグに対して直接スタイルを適用しない
例えばh2タグに対して直接スタイリングを記述してしまうと、「こっちのページでは、同じスタイルをh3に適用したい」となった場合に困るよね、という話。
スタイルを記述するクラスを定義して、そのクラスを要素に付与するのがいい。
ただし別タグと置換しにくいimgなどは許容する場合も。
影響範囲がみだりに広すぎない
CSSは多くの積み重ねの上に見た目が決定される(カスケード・詳細度・継承……)。
不必要に影響範囲が広いコードがあると、変更のために上書きが必要になり、詳細度を高めたり!importantを使い始めたりとカオスになりかねない。
カオスを生まないために、
- 影響範囲の広いCSSに含めるスタイリングは最小限に
- スコープを絞り、影響範囲を狭くする
特定のコンテキストにみだりに依存していない
1つ前の話と逆で、スコープを狭めすぎても良くない、という話
例:
<div class="main_module"> <h2 class="title">コンテンツタイトル</h2> </div>
.main_module .title { font-size: 16px; font-weight: bold; }
このHTML部分を見ると、titleクラスは他のパーツでも使えそうに見えてしまう。しかしこのCSS実装では、main_moduleクラスの範囲内でしか使用できない。
コンテンツのタイトル部分のような使いまわしたいスタイリングは、コンテキストを絞らずに記述する必要がある。
詳細度がみだりに高くない
詳細度が高いと以下のようなデメリットが。
- セレクターの見通しが悪くなる
- 他の要素に対する依存が多くなる
- 密結合になり、特定のコンテキストへの依存も発生しがち
不必要に詳細度を高くしていないか気をつける。
例:
<div class="media main_module"> <h2 class="title">コンテンツタイトル</h2> </div>
.media.main_module .title { font-size: 16px; font-weight: bold; }
mediaとmain_moduleの両方を指定しているが、(上書き等の理由がなければ)1つでいい。可能な限り詳細度は下げる。
改善例:
.media .title { font-size: 16px; font-weight: bold; }
クラス名から影響範囲が想像できる
ここからはクラス名の話。
先ほども出した例ですが、今度はこのtitleクラスをこのmain_moduleクラスの範囲内でだけ使いたい場合にどうすべきか。
<div class="main_module"> <h2 class="title">コンテンツタイトル</h2> </div>
.main_module .title { font-size: 16px; font-weight: bold; }
先ほども書いたように、このクラス名では他のモジュールでも使いまわせそうな命名になっており混乱を招きます。
この場合、main_module内でのみ使えるクラスとわかる命名にすべき。
<div id="main_module"> <h2 class="main_module_title">コンテンツタイトル</h2> </div>
.main_module_title { font-size: 16px; font-weight: bold; }
個人的には、この場合.main_module.main_module_titleとしたほうが、意図に反して他のモジュールで.main_module_titleを使われる心配がなくなり良さそうに思うんですが、どうだろう。
ともあれ、機能が伝わる変数名にしよう、という話はCSSに限らずプログラミング全般で大事にすべき話ですね。
クラス名から見た目・機能・役割が想像できる
これも命名の話で、title1, title2, title3のようなクラス名ではなく、page-title, section-title, sub-titleのような機能を示す名前をつけよう、という話。
拡張しやすい
シングルクラス設計ではなく、マルチクラス設計がいいよ、とのこと。
HTML要素ありきで、要素に対して1つのクラスをを当てていくのではなくて、スタイリングの役割ごとにクラスを分割していこう、という話。
BootstrapやTailwindなどのCSSフレームワークが用意しているクラスのように、機能ごとにクラスを作っていく方法、と理解してます。
これは確かに大事そうだなあと思う反面、しっかり設計思想をチーム内で共有した上で進める必要がありそう。場当たり的にそれっぽいことをやりはじめてしまうと、それはそれでカオスを生みそうです。
感想
いや〜、既存コードのCSSの修正の際に、意図したスタイリングが上手くできずに詳細度を高めたり!importantをつけてその場しのぎで対応した記憶が呼び起こされて、聞いててツラくなるお話でした……。
今回いくつか例に出したシンプルなコードだけ見ると「そうはならんやろ」と思っても、コードが複雑になってくると同じような良くないCSSを書いてしまうことが往々にしてあると思ってます。
カオスを生み出さないためにも、プロジェクトが小さい段階でCSS設計を検討すること、また設計を大きく変えられないような大きくなったプロジェクトでも、今回のようなポイントを押さえて「良くないCSS」を書かないようにすることが大事なんだろうなあと思いました。
ところで、VueやReactなど、コンポーネントに分割されたコードの場合はまたCSS設計の考え方が変わってきそうだと思ってます。そのあたりの関係性も勉強しておきたい。