CSSの詳細度について思う所、わかったような気がする事を「きっとこうだろう」ベースでまとめたもの。
気になる点などがあればガシガシ突っ込んで貰えると嬉しいです。
詳細度が高いと何が問題なのか?
値が上書きできない。
→ 上書きするためにには 同じ or それ以上の詳細度ポイントを稼がなければならない。
詳細度の高い記述の後に詳細度の低い記述が来ると…
→ 直感的に見て理解しづらいCSSの構造ができあがってしまう。
詳細度グラフの計測
詳細度は緩やかな右上がりのカーブになっているのが理想的
詳細度とは別にCSSには「コードの記述順」という概念もある。
下方のコードが上方のコードを上書きする構成、が理想的。
詳細度グラフの適切な管理
SCSSなどを使って複数ファイルを連結すると意識が飛びがち
ポイント
- 子孫セレクタの乱用を避ける(適用範囲の限定にしても2段階で十分)
- 直接importしない(急激な詳細度低下の)
子孫セレクタの乱用を避ける
子孫セレクタの利用はCSSパフォーマンスを低下させるだけでなく、
親子階層内でのむやみなプロパティの上書き合戦を招きがち。
スキンのスタイリングを確実に末尾nodeで指定するようにし、
親階層での指定は構造の定義に留めるのが良さそう。
Bad pattern
.article{
.title{
font-weight: bold;
.evecatch{
width: 100%;
}
.subtitle{
font-weight: 100; // 上書き合戦
color: gray;
}
}
}
Good pattern
.article{
// スキン
.maintitle{
font-weight: bold;
}
.subtitle{
font-weight: 100;
color: gray;
}
// 構造
.evecatch{
width: 100%;
}
}
直接importしない
直接importすると、import先で急激な詳細度の低下が起こるかも知れない。
ある程度の詳細度を稼ぐ事が前提のブロックでは、直接@import
するのでなく、コンテキスト内での@import
を行う。
Bad pattern
@import "article"
.article{
.title{
font-weight: bold;
}
}
Good pattern
.article{
@import "article"
}
.title{
font-weight: bold;
}
先ほどの子孫セレクタの乱用を…と併せて使うとSCSSのネスト機能を一切使わないという選択肢もありそうです。
BEMの伝えたかった事
詳細度の管理において、BEMの様な単一class名の設計は非常に重要です。
一部ではCSSの適用範囲を適切に限定するために、子孫セレクタを乱用する(特にSCSSを利用する環境上では)傾向が見られがちでしたが、詳細度の問題やCSSパフォーマンスの観点を考えると、これは余りいい方法とは言えません。
BEMの様な冗長な命名規則を用いないにしても、CSSの適用範囲を限定するには少なくとも2階層程度の制約がアレば十分そうなものなので、CSSセレクタの定義は以下の様な親子関係程度に留めることが出来そうです
.{名前空間} .{要素セレクタ}[.{modifier}]
OOCSSの伝えたかったこと
子孫セレクタを乱用する中で生じるもう一つの問題は、子孫ツリー上でのプロパティの継承合戦です。
この点に関してOOCSSは「デザインのオブジェクト指向」、「スキンと構造の分離」という便利な観点を提供してくれます。
デザインをひとまとまりで考えるのではなく、スキンと構造というひとまとまりの組み合わせを、オブジェクトに適用させる、と言うのは非常に大事な観点になってきます。
DOMの子孫関係とCSSの子孫関係を常に同じに考える必要はありません。ココのDOMが(親ではなく)自らにつけられたClass名を起点にスタイリングされる、ということは非常に重要な意味とわかりやすさを提供してくれます。
全てのデザインがHTMLの親子関係とは分離され、「構造」「スキン」の2要素のクラス名の組み合わせで定義される時、きっとCSSは理解しやすく、またメンテナンス性の高い多くの変更に耐えうる構造になると思います。