CSSスタイルのカプセル化-パート1:問題

ミレニアムの変わり目にウェブが成長した主な要因はコンテンツの消費でした 。 サイトは、訪問者に有用な情報やエンターテイメントコンテンツを提供するために作成されました。 しかし、近年では、ユーザーにコンテンツ生成サービス(テキストおよび画像エディター、スプレッドシート、インスタントメッセンジャーなど)を提供するWebリソースの重要性が急激に高まっています。 これにより、サイトが単一ページのアプリケーションに変換され、以前はアプリケーションプログラムの特権であったWebへの複雑なインターフェイスが移行されました。



これらの変換と移行の過程で、Webインターフェイスの作成と保守の複雑さの増大が、その複雑さの増大を大幅に上回ったことが判明しました。 彼らは、それらをモジュールに分割し、抽象化し、カプセル化することで問題を解決しようとしました(そして今も試みています)。 この目的のために、多数のJavaScriptフレームワーク( Backbone



Ember



Angular



)、HTMLテンプレートエンジン( Jade



Handlebars



)、依存関係管理システム( RequireJS



)などが作成されました。



CSSはこの観点から最も困難であることが判明しました。言語の設計により、接続されたCSSファイルまたはstyle



タグで宣言されたプロパティは、DOMツリーの要素の表示に影響を与える可能性があります。



タスクの形式化。


簡単にするために、すべてのJavaScriptコードは、お互いについて何も知らないモジュールで囲まれ、作業に必要なものすべてをカプセル化するとします。 モジュールは、そのHTML表現を生成する方法( ブロックと呼びましょう)と、DOMツリーのどこに挿入するかを知っています。 この場合、ブロックは互いに入れ子にすることができます。 紐付けレベルでは、ブロックはルート要素子要素で構成されます。

タスクは、ブロックの要素の表示が、HTML表現と対応するCSSファイルとstyle



タグの意図的な変更によってのみ影響を受ける可能性があることです。



ブロック要素の表示における不注意な変更は、 スタイルの漏れと呼ばれます



スタイルリークは、他のブロックの要素のプロパティの変更( プロパティリーク )と、DOMツリーの変更( カスケードリーク )の両方で発生する可能性があります。



スタイルリークソース


ブロック自体を考慮すると、スタイルのリークは外部と外部の両方から発生する可能性があります。 1つのユニットの外部リークは別のユニットの外部リークになるという事実により、リークの分類は外部リークの場合に限定できます。



1.プロパティの継承


CSSプロパティに要素の明示的な値がない場合、デフォルト値が使用されます。 この値がinherit



場合、プロパティ値は親要素のプロパティ値と等しく設定されます。

したがって、現在のブロックのルート要素は、定義により、別のブロックに属する親のスタイルを継承できます。



例えば

 .outer-block{ color: red; }
      
      





 <div class="outer-block">     <div class="current-block">   -   </div> </div>
      
      





jsfiddle.netを見てください



2.プロパティの適合性


CSSプロパティに要素の明示的な値がない場合、デフォルト値が使用されます。 このプロパティが親要素のプロパティ(たとえば、デフォルト値がauto



width



およびheight



プロパティとして)または模倣(たとえば、デフォルト値がtransparent



background-color



プロパティとして)に調整されている場合、エンドユーザーは、親要素スタイルが子要素スタイルにリークしました。



例えば

 .outer-block{ background: red; }
      
      





 <div class="outer-block">     <div class="current-block">   -   </div> </div>
      
      





jsfiddle.netを見てください



親要素のスタイルは子要素に正式に適用されないため、適合によるスタイルリークの存在そのものを疑問視できることに注意してください。 しかし、 正式な観点からは、スタイルの適合性がカプセル化に明らかに違反していることを認めなければなりません。 実用的な証拠として、著者は、 アヒルのテストを使用する好奇心reader盛な読者を提供しています。



3.連鎖するカオス


セレクターのターゲット要素へのスタイルの適用は、3段階で行われます。

最初の段階では、ターゲット要素のセレクタに対応するすべての要素がDOMツリー全体から選択されます。 たとえば、 .current-block h3



セレクターの場合、最初の段階で、 h3



タグを持つすべての要素が選択されます。 選択スペースをDOMツリーの任意の部分に制限する方法はありません。

2番目の段階では、選択された要素は、ターゲット要素の親要素を走査することにより、セレクタに準拠するためにフィルタリングされます。 子孫コンビネータを使用する場合、一致の検索はDOMツリーのルート要素までずっと進むことができます。 姉妹コンビネータを使用する場合(一般的な兄弟コンビネータ)-最初の姉妹要素まで。



例えば

 .current-block h3 { background: blue; } .outer-block h3 { background: red; }
      
      





 <div class="outer-block"> <h3>   </h3> <div class="current-block"> <h3>  -  </h3> </div> </div>
      
      





jsfiddle.netを見てください



サーチスペースを制限する唯一の方法は、子コンビネータと最も近い兄弟コンビネータを使用することです。 これを行うには、ターゲット要素からブロックのルート要素へのDOMツリーで正確なパスを指定する必要があります。これにより、CSSとHTMLコードの一貫性が向上します。



3番目の段階では、選択およびフィルタリングされたターゲット要素にスタイルプロパティが割り当てられます。 さらに、それぞれが独自のプロパティバリアントを持つ複数のセレクタが同じターゲット要素を要求する場合、プロパティ値はセレクタの特異性に基づいて決定され、等しい場合は宣言順序に基づいて決定されます。



したがって、特定の条件下(使用されるコンビネーター、特異性比、宣言順序)で、外部ブロックの要素のスタイルは、ネストされたブロックの要素のスタイルに影響を与える可能性があります。 ターゲット要素を選択してフィルタリングするDOMツリーの領域を指定できる場合、この影響は回避できます。



4.位置調整


セレクターで兄弟コンビネーター( +



および~



)または疑似クラス( :first-child



など)を使用する場合、ブロック要素はDOMツリー内のブロックの位置に応じて表示を変更できます。



例えば



 .block { background: red; } .block + .block { background: blue; }
      
      





 <div class="block"> <h3> ,         </h3> </div> <div class="block"> <h3> </h3> </div>
      
      





jsfiddle.netを見てください



プロパティの整合性の場合と同様に、多くの開発者が位置調整が非常に有用であることに気付く価値があります。 記事の著者は、条件の明確化がスタイルのカプセル化に違反しているため、条件がブロックの境界を超えるまで、彼らと連帯しています。



明らかに、CSSスタイルの理想的なカプセル化は、リークの可能性を排除するはずです。



記事の2番目の部分(「CSSスタイルのカプセル化-パート2ソリューション」)では、現在のアプローチ(OOCSS、SMACSS、ACSS、BEM、CSSプリプロセッサー)がどのように理想に対応するか、その分類について分析します。



有益なアドバイスと建設的な批判に感謝します。



All Articles