Enduring CSS 02
CSSの規模問題
ほとんどのプロジェクトでは、CSSはいくつかの簡単な規則から始まります。初めからCSSのメンテナンス性を問題とするためには、何かの規則を酷く扱わなければなりません。
しかし、プロジェクトが成長するにつれて、CSSも成長していきます。つまり、要件がより複雑になります。より多くのエンジニアがCSSを関与していきます。極端なケースやブラウザの回避策を考慮して組み込む必要があります。これらは容易なことではありません。
謙虚なウィジェットへの要求が高まっていることをよく考えてみましょう。
「ウィジェットがサイドバーにあるときは、フォントサイズを小さくすることはできますか?」
「ホームページを開いているときに、ウィジェットの背景色を変えることはできますか?」
「ウィジェット内のものを、大きなビューポートで縦に積み重ねることはできますか?」
「ウィジェットが製品ページのサイドバーにあるとき、フォントの色を変更する必要があります」
長い間、基本セレクタで全体へのオーバーライドを記述する必要がありました。必要なセレクタについて考えてみましょう。
code:ecss01.css
.widget {
/* 基本スタイル */
}
aside#sidebar .widget {
/* サイドバーの詳細度 */
}
body.home-page aside#sidebar .widget {
/* Home page におけるサイドバーの詳細度 */
}
@media (min-width: 600px) {
.widget {
/* 600px以上での基本スタイル */
}
aside#sidebar .widget {
/* 600px以上におけるサイドバーの詳細度 */
}
body.home-page aside#sidebar .widget {
/* Home page における600px以上におけるサイドバーの詳細度 */
}
}
body.product-page .widget {
/* Product pageでの詳細度 */
}
body.product-page aside#sidebar .widget {
/* Product pageでのサイドバーの詳細度 */
}
これが拡張したかったCSSだったら、いくつかの基本的なオーサリングの問題があります。これらの規則で明らかになった問題のいくつか考えてみましょう。
詳細度
規模のCSSの最初の大きな問題は、詳細度の問題を回避したいということです。通常、詳細度は便利なものです。これにより、CSSに何らかの形のロジックを導入することができます。他よりも具体的なスタイルがブラウザに適用されます。
上の例ではこれを示しています。異なるルールが異なる結果に適用されます(たとえば、サイドバーにデフォルトのスタイルを上書きする場合など)。
さて、CSSセレクタは、ID、クラス、属性とセレクタタイプらの任意の組み合わせで構成できます。レスポンシブデザインでは、その中にメディアクエリーも投じることもできます。
セレクターの詳細度は以下のように計算される。IDセレクタの個数を数えて(= a)クラスセレクタ、属性セレクタ、および擬似クラスの個数を数えて(= b)セレクタタイプと擬似セレクタの個数を数えて(= c)全称セレクタを無視します。否定擬似クラス内のセレクタは他のものと同様にカウントされますが、否定自体は詳細度の計算では擬似クラスとは見なされません。3つの数字a-b-c(大きな基数を持つ数字で)を連結すると、詳細度が得られます。
そこに欠けている重要なものの1つに、スタイル属性があります。他の情報によると、 スタイル属性内の宣言は、その属性を有する要素に適用される。この宣言は、カスケードにおいては、[ 出自は作者であって, 詳細度はどのセレクタよりも高い]ものと見なされる。
したがって、要素のスタイル属性に適用されるスタイルは、CSSの同等のルールよりも具体的になります。
いずれにしても、IDセレクタはクラスベースのセレクタよりも無限に限定されています。これにより、IDベースのセレクタを含むセレクタを上書きするのがはるかに難しくなります。例えば、サイドバーのウィジェットではこれは機能しません。
code:ecss02.css
.widget {
/* サイドバーでのウィジェット */
}
aside#sidebar .widget {
/* サイドバーでの、aside要素とIDで紐付けられたウィジェット */
}
.class-on-sidebar .widget {
/* 何故か機能しない */
}
この例では、サイドバー要素(サイドバーのIDを持つaside要素)にHTMLのクラス.class-on-sidebarを適用し、IDベースのセレクタよりもCSSの下位にある要素を選択しています。ただし、このルールでは適用されません。
W3Cの仕様での詳細度について学んでいますので、これらの詳細度を計算することができます。
順番を出力しましょう。左から右に、以下がセレクターの後に関連する数(インラインスタイルの数、IDセレクタの数、クラスセレクタの数、セレクタタイプの数)です。
table:ルールの詳細度について
selector inline ID class type
------------------------------- ------------ ------------ ------------ ------------
.widget 0 0 1 0
aside#sidebar .widget 0 1 1 1
.class-on-sidebar .widget 0 0 2 0
したがって、ここでは、中央のセレクターが最後のセレクターよりも詳細度が高いことがわかります。がっかり。
単一のファイルまたは小さいファイルでは、それほど大きな問題ではありません。より具体的なルールを作成するだけです。しかしコードベースのCSSが、複数の小さなCSSファイルに分割されている場合、上書きしないようにするルールを見つけることは、不必要な負担になる可能性があります。
さて、この問題はIDセレクタによる固有の問題ではありません。これはスタイルシートの不等な重み付きによるセレクタの問題です。フライウェイト級に対抗するためにヘビー級のボクサーになることだと考えてみましょう。それは公正なコンテストではありませんね。
実際に使用されたセレクタより重要なのは、使用されたセレクタ間での同じレベルの競技場を作ることです。
このセレクタの不一致スープは、詳細度問題の要点です。何百ものルールを持つCSSを持っていれば、不必要な詳細度は大きな問題になり始めます(これは専門用語です)。
結論として、ますます増大していくCSSにおいて詳細度というのは、対処する必要がある問題です。
セレクタに結びつけられたマークアップ構造
大規模なCSSを作成する際にセレクタタイプを使用する場合の別の典型的な偽のパスは、特定のマークアップに関連するセレクタ。例えば:
code:ecss03.css
aside#sidebar ul > li a {
/* スタイル */
}
この場合、 #sidebar のIDを持つ aside 要素の中に ul の直接の子である li の中に aタグが必要です。やれやれ。
これらのスタイルを別の場所のdivに適用したい場合はどうなるでしょうか?または他のマークアップ構造においてそれを適用する場合は?
ルールを特定のマークアップ構造に不必要に結びつけただけです。a や spanタグの(一見)些細なものにクラスを追加するのはばかばかしく見えるかもしれないので、しばしばこのようにしてしまいがちです。しかし、ECSSの終わりに達すると、その練習を避けるために納得することができれば幸いです。
段階的
通常、CSSのカスケード(段階的)な部分は便利です。たとえ使用されているセレクタ間で詳細度が非常に等しいとしても、既存のルールよりも上にCSSファイルを適用して同等のルールをさらに上げることができます。
しかし、大規模なコードでは、既存のコードを修正するのではなく、継続的にCSSを追加することになります。
これは、いくつかの理由によって発生します。一例として、他の言語に精通している作者は、自信を持って既存のコードを削除または修正できるようにするために、CSSコードへの信頼または親密な知識が不足していることがあります。したがって、彼らは安全な選択を取って、より特定のルールセットを使用して既存のルールを上書きします。
実際には既存のスタイルの一番下に、機能を完了させるために必要なセレクタがあれば、新しいルールを追加することを意味します。
このようにカスケードにおける問題の傾向は、時間と反復に伴い、CSSが冗長なルールで膨れ上がってしまうことです。このCSSの消費者(ユーザー)は、ブラウザが本来必要としない粗悪なものをダウンロードしています。
まとめ
現時点で、大規模化に対処するために苦労しているCSSの症状である、高度な問題のいくつかを取り上げました。私たちは、詳細度とカスケードにおける問題を見てきました。次の章では、大規模なCSSを酷使し、それらに存在する欠点を検討するという、受け入れられた知恵とアプローチを見ていきます。