web-dev-qa-db-ja.com

ブラウザがCSSセレクタと右から左に一致するのはなぜですか。

CSSセレクタは、ブラウザエンジンによって右から左へと照合されます。それで、彼らは最初に子供を見つけて、それから彼らが規則の残りの部分にマッチするかどうか見るために彼らの両親を調べます。

  1. どうしてこれなの?
  2. 仕様が言っているという理由だけでですか?
  3. 左から右に評価された場合、最終的なレイアウトに影響しますか?

私にとって最も簡単な方法は、要素数の少ないセレクターを使用することです。そのため、最初にIDを使用します(1つの要素のみが返されるため)。その場合、クラスやノードの数が最も少ない要素、たとえばページ上にはスパンが1つしかない可能性があるため、スパンを参照するルールを使用してそのノードに直接移動します。

これが私の主張を裏付けるリンクです。

  1. http://code.google.com/speed/page-speed/docs/rendering.html
  2. https://developer.mozilla.org/en/Writing_Efficient_CSS

それは、1人でなければならない子供のすべての親ではなく、親のすべての子供(多くの可能性がある)を見なくてもよいようにするためにこのようにして行われるように思えます。 DOMが深くても、RTLマッチングでは複数ではなく、レベルごとに1つのノードしか調べられません。 CSSセレクターのLTRとRTLのどちらを評価する方が簡単でしょうか?

527
tgandrews

ブラウザがセレクターマッチングを行っているとき、それは1つの要素(スタイルを決定しようとしているもの)とあなたのすべてのルールとそれらのセレクターを持ち、どのルールがその要素にマッチするか見つける必要があります。これは通常のjQueryのものとは異なります。たとえば、セレクタが1つしかなく、そのセレクタに一致するすべての要素を見つける必要がある場合などです。

セレクタとそのセレクタと比較する要素が1つだけの場合は、左から右にすると意味があります。しかし、それは明らかにブラウザの状況ではありません。ブラウザはGmailやその他何でもレンダリングしようとしていて、スタイルしようとしている<span>とGmailがスタイルシートに入れる10,000以上のルールを持っています(私はその数字を計算していません)。

特に、ブラウザが検討しているセレクタのほとんどを見ている状況では問題の要素と一致しません。そのため、問題はセレクタができるだけ速く一致しないと判断することになります。一致する場合にそれが少し余分な仕事を必要とするならば、あなたがまだあなたがまだ一致しない場合にあなたが救うすべての仕事のために勝つ。

あなたが単にあなたの要素に対してセレクタの右端の部分を一致させることから始めるならば、それはそれが一致しない、そしてあなたがしている可能性があります。それが一致するならば、あなたはより多くの仕事をしなければなりません、しかしあなたの木の深さに比例しているだけで、それはほとんどの場合それほど大きくありません。

一方、セレクタの左端の部分を照合することから始めるとしたら、何に照合しますか。あなたはそれにマッチするかもしれないノードを探して、DOMを歩き始めなければなりません。一番左の部分に一致するものがないことを発見するだけでしばらく時間がかかります。

そのため、ブラウザは右側から一致します。それは明白な出発点を与えて、あなたが候補者セレクタの大部分を非常に速く取り除くことを可能にします。いくらかのデータを http://groups.google.com/group/mozilla.dev.tech.layout/browse_thread/thread/b185e455a0b3562a/7db34de545c17665 で見ることができますが、その結果、特に2年前のGmailでは、(rule、element)ペアの70%について、ルールの右端のセレクターのtag/class/id部分を調べただけでルールが一致しないと判断できることがわかりました。 Mozillaのページロードパフォーマンステストスイートに対応する数は72%でした。ですから、できる限り早くすべてのルールのうち2/3を取り除き、それから残りの1/3のマッチングについてのみ心配することをお勧めします。

また、ブラウザがすでに一致しないルールを一致させようとしても回避するためにすでに行っている他の最適化もあります。例えば、一番右のセレクターがIDを持ち、そのIDが要素のIDと一致しない場合、Geckoではそのセレクターをその要素とまったく一致させることはできません。試行される "IDを持つセレクター"のセットです。要素のIDのハッシュテーブルルックアップからきています。そのため、これはのタグ/クラス/ IDだけを考慮しても一致しないという、かなり一致する可能性が高いルールの70%です。一番右のセレクタ.

795
Boris Zbarsky

右から左への解析は、ボトムアップ解析とも呼ばれ、実際にはブラウザにとって効率的です。

次の点を考慮してください。

#menu ul li a { color: #00f; }

ブラウザは、まずa、次にli、次にul、次に#menuをチェックします。

これは、ブラウザがページをスキャンしているときに、現在の要素/ノードと以前にスキャンしたすべてのノード/要素を確認するだけでよいためです。

注意すべきことは、ブラウザは完全なタグ/ノードを取得した瞬間に処理を開始しますで、スクリプトが見つかった場合を除いてページ全体を待つ必要がないということです。スクリプトの実行を完了し、次に進みます。

逆の場合は、ブラウザが最初のチェックでスキャンしていた要素を見つけたため、非効率的になりますが、それ以降はすべての追加セレクタについてドキュメントを調べ続けることを余儀なくされました。このためにはブラウザはHTML全体を持っている必要があり、それがCSSペインティングを開始する前にページ全体をスキャンする必要があるかもしれません。

これは、ほとんどのライブラリがDOMを解析する方法に反します。そこでDOMは構築されていて、最初の要素を見つけてその中の他の要素と突き合わせるだけでページ全体をスキャンする必要はありません。

27
aWebDeveloper

それはより特定的なものからそれほど特定的でないものへのカスケードを可能にします。それはまた応用において短絡を許す。親ルールが適用されるすべての側面でより具体的なルールが適用される場合、すべての親ルールは無視されます。親に他のビットがある場合は、それらが適用されます。

逆に行った場合は、親に従ってフォーマットしてから、子に何か違うものがあるたびに上書きします。長い目で見れば、これはすでに処理されているルール内の項目を無視するよりもはるかに多くの作業です。

19