この記事は、元の著者である @csswizardry の許可を得て、彼のブログの記事「Cyclomatic Complexity: Logic in CSS」を翻訳したものです。元々は私の個人ブログで公開されました: Chewing Taste
過去の長い間、CSS にはロジックがないと誰もが言っていました。つまり、CSS には制御フローがなく、その方法に似たものは何もありません。他のプログラミング言語では CSS が整理されます。 CSS にはロジックが本質的に欠如しているため、プリプロセッサの出現につながりました。ただし、業界では CSS プリプロセッサについてさまざまな意見があります。プリプロセッサを支持する人は、CSS に欠けている機能を補うと信じています。一方、プリプロセッサに反対する人は、CSS は本来の設計では論理的であるべきではないと信じています。本質的に論理的ではありません。プリプロセッサの概念はまったく導入されるべきではありません。
しかし、最近、独特の考え方が突然頭に浮かびました。 CSS にはロジックがあるような気がします。実際にそのように考えている人はほとんどいません。おそらくこれが、CSS にはロジックが欠けていると私たちが常に考える最大の理由です。
複合セレクターは、本体部分 + 条件部分 として理解できることがわかりました。まず、例を見てみましょう:
div.sidebar .login-box a.btn span { /*...*/}
この複合セレクターでは、メイン部分はspanで、条件部分はIF (.btn内) AND IF (on a) AND IF (.login-box内) AND IFです。 (サイドバー内) AND IF (div 上)。
言い換えると、セレクターの各部分は、セレクターを解析するときに満たされる (または満たされない) 必要がある if ステートメントです。この微妙で新しい理解を得て、今までに書いた CSS コードを振り返ってみると、セレクターが適切に記述されているか、不適切に記述されているかが効率に直接影響することがわかります。本当に次のロジックを書くのでしょうか? (疑似コード):
@if exists(span) { @if is-inside(.btn) { @if is-on(a) { @if is-inside(.login-box) { @if is-inside(.sidebar) { @if is-on(div) { # Do this. } } } } }}
そうではないかもしれません。これはあまりにも間接的で、冗長すぎるように思えます。これを書くだけでよいかもしれません:
@if exists(.btn-text) { # Do this.}
セレクターに制限のレイヤーを追加するたびに、実際には if ステートメントを追加することになります。これは循環的複雑性を引き起こす可能性があります。
ソフトウェアエンジニアリングでは、循環的複雑度はプログラムの複雑さの尺度であり、通常、プログラム内の制御フロー (if、else、while など) の数をカウントします。プログラム内の制御フローが増えるほど、循環的な複雑さは高くなります。循環的複雑度が高くなるほど、コードの導出が難しくなります
ブラウザーが作成したセレクターを右から左に解釈する方法に注目する価値があります。セレクターを作成するときに最初に頭に浮かぶ疑問が「これはスパン要素ですか?」である場合、通常はセレクターを冗長にしすぎます。別の角度から考えて、明確かつ正確なセレクター ルールを作成し、冗長な条件ステートメントを完全に放棄する必要があります。 広すぎるルールを記述しないでください。その結果、作成したセレクターが一致の開始時に多数の DOM 要素を選択し、その後、一致したオブジェクトを削除するために徐々に多くの条件ステートメントを使用する必要があります。より良いアプローチは、セレクターのルール解析の開始時から可能な限り少数の要素と一致するようにすることです。
循環的複雑性は CSS にとって比較的高レベルの原則ですが、作成するセレクターに含まれるロジックを考慮するためにそれを使用すると、より良いコードを作成できる可能性があります。
従うのが簡単な小さなルールをいくつか
セレクターは CSS 構造の最も基本的な部分です。作成するコードが合理的で十分に簡潔であることを確認してください。