web-dev-qa-db-ja.com

CSSはブラウザによってどのように適用され、再描画はブラウザによって影響を受けますか?

単一のスタイルシート<link>を持つHTMLページがあるとしましょう。ブラウザはこのスタイルシートのルールをどのように取得してHTMLに適用しますか?高速化する方法については質問していません。レンダリング自体がどのように処理されるかを知りたいのです。

スタイルシートを解析して結果を段階的にレンダリングするときに、各ルールを1つずつ適用しますか?または、CSSファイルの内容が完全にダウンロードされてから完全に評価され、次にがHTMLに一度に適用されますか?または、他の何か?

以前に回答を投稿した後、これを尋ねます レンダリング速度に影響するCSSルールの順序に関する質問 、スタイルがレンダリングされたasスタイルシートがロードされたため、最初のルールが最後のルールの前に適用され、一度にすべてが適用されるわけではありません。どこでアイデアを思いついたのかわかりませんが、それは私がいつも考えていたものです。

サーバーで次のようなデモを試しました。

<!DOCTYPE html>
<html>
<head>
   <title>Test</title>
   <link rel="stylesheet" href="test.css" />
</head>
<body></body>
</html>

test.cssコンテンツ:

html { background:green }
/* thousands of lines of irrelevant CSS to make the download slow */
html { background:red }

Firefox 5でテストすると、最初は緑が表示され、次に赤に変わると予想していました。それは起こりませんでした。ルールが競合する2つの別々のスタイルシートを試してみたところ、同じ結果が得られました。多くの組み合わせの後、私がそれを機能させる唯一の方法は、<style>のインライン<head>ブロックであり、競合するルールは<link><body>から来ています(リンクタグを除いて、本体自体は完全に空でした)。 <html>タグでインラインstyle属性を使用し、このスタイルシートをロードしても、期待したちらつきは発生しませんでした。

再描画はCSSによってanyの方法で影響を受けますか、またはスタイルシート全体がダウンロードされ、ルールが計算された後に一度に適用される最終出力です最終出力は? CSSファイルはHTML自体と並行してダウンロードしますか、それとも(スクリプトタグのように)ブロックしますか?これは実際にどのように機能しますか?

私は最適化のヒントを探していません。将来それらを引用できるように、この主題に関する信頼できる参考文献を探しています。無関係な資料を大量に見つけずにこの情報を検索することは非常に困難でした。概要:

  • いずれかのが適用される前にダウンロードされたすべてのCSSコンテンツはありますか? (参考にしてください)
  • これは、@import、複数の<link>s、インラインスタイル属性、ヘッド内の<style>ブロック、さまざまなレンダリングエンジンなどの影響を受けますか?
  • CSSコンテンツのダウンロードは、HTMLドキュメント自体のダウンロードをブロックしますか?
32
Wesley Murch

ブラウザはこのスタイルシートのルールをどのように取得してHTMLに適用しますか?

通常、これはストリーミング方式で行われます。ブラウザはHTMLタグをストリームとして読み取り、これまでに見た要素に可能なルールを適用します。 (明らかに、これは単純化です。)

興味深い関連Q&A: CSSセレクターを使用してストリーミングパーサー(SAXストリームなど)からHTML要素を収集します (私が考えている記事を検索している間の転換)。


ああ、ここにあります: 親セレクターがない理由

私たちはしばしば私たちのページを要素と内容でいっぱいのこれらの完全で完全な文書と考えます。ただし、ブラウザはストリームのようにドキュメントを処理するように設計されています。サーバーからドキュメントの受信を開始し、完全にダウンロードされる前にドキュメントをレンダリングできます。各ノードは評価され、受信時にビューポートにレンダリングされます。

サンプルドキュメントの本文を見てください。

<body>
   <div id="content">
      <div class="module intro">
         <p>Lorem Ipsum</p>
      </div>
      <div class="module">
         <p>Lorem Ipsum</p>
         <p>Lorem Ipsum</p>
         <p>Lorem Ipsum <span>Test</span></p>
      </div>
   </div>
</body>

ブラウザは上部から起動し、body要素が表示されます。この時点で、それは空であると考えています。それは他に何も評価していません。ブラウザは、計算されたスタイルが何であるかを判断し、それらを要素に適用します。フォント、色、線の高さは何ですか?これを理解した後、画面にペイントします。

次に、IDがdivcontent要素が表示されます。繰り返しますが、この時点では、空であると見なされます。それは他に何も評価していません。ブラウザがスタイルを把握し、divがペイントされます。ブラウザは、ボディを再描画する必要があるかどうかを判断します。要素は広くなったのですか、それとも高くなったのですか? (他にも考慮事項があると思いますが、幅と高さの変更は、子要素が親に与える最も一般的な影響です。)

このプロセスは、ドキュメントの最後に到達するまで続きます。

CSSは右から左に評価されます。

CSSルールが特定の要素に適用されるかどうかを判断するには、ルールの右側から開始し、左側に向かって機能します。

body div#content p { color: #003366; }のようなルールがある場合、すべての要素について(ページにレンダリングされるときに)、最初にそれが段落要素であるかどうかを尋ねられます。そうである場合は、DOMを上に移動し、コンテンツのIDを持つdivであるかどうかを確認します。探しているものが見つかると、bodyに到達するまでDOMを上っていきます。

ブラウザは、右から左に操作することで、ビューポートにペイントしようとしているこの特定の要素にルールが適用されるかどうかをはるかに速く判断できます。どのルールのパフォーマンスが高いか低いかを判断するには、スタイルを要素に適用できるかどうかを判断するために評価する必要のあるノードの数を把握する必要があります。


では、なぜスタイルシートのコンテンツが段階的に適用されなかったのでしょうか(最初に緑、次に赤)。

think答えは、外部スタイルシートはダウンロード時に解析されるということです、ただし、スタイルシート全体が解析されるまでappliedされません。確かに、スタイルシートを解析する際に、ブラウザーは不要で冗長なCSSルールを最適化します。

今のところそれを裏付ける証拠はありませんが、その説明は私には合理的に聞こえ、外部スタイルとインラインスタイルの両方であなたが見ているものと一致しています。

16
Matt Ball

理解しておくべき最初のそして最も重要なことは、すべてのCSSがダウンロードされるまで、ブラウザーはページのペイントを開始できないということです。 (W3C仕様では、CSSリンクはヘッドでのみ許可されると規定されているため、bodyタグのスタイルシートへのリンクを開始すると、ブラウザーによってこの状況の処理が異なることに注意してください。)

これで、Webページがストリームとして読み取られ、CSSルールがHTML要素がページに入力されるときに適用されます。以下にリンクされているGoogleの記事を引用するには:

ブラウザがHTMLを解析すると、表示されるすべての要素を表す内部ドキュメントツリーが構築されます。次に、標準のCSSカスケード、継承、および順序付けのルールに従って、要素をさまざまなスタイルシートで指定されたスタイルに一致させます。

だから今あなたの質問に対処するために:

スタイルシートを解析して結果を段階的にレンダリングするときに、各ルールを1つずつ適用しますか?または、CSSファイルのコンテンツが完全にダウンロードされ、完全に評価されてから、HTMLに一度に適用されますか?または、他の何か?

すべてのCSSをダウンロードしてから、トップダウンでドキュメントのペイントを開始します。

Firefox 5でテストすると、最初は緑が表示され、次に赤に変わると予想していました。それは起こりませんでした。ルールが競合する2つの別々のスタイルシートを試してみたところ、同じ結果が得られました。

これは、CSSがすべて最初にダウンロードされ、次に要素に遭遇したときに、カスケードの動作方法のために赤いスタイルのみが適用されたためです。

多くの組み合わせの後、私がそれを機能させる唯一の方法は、<style>のインライン<head>ブロックであり、競合するルールは<link><body>から来ています。

これが発生した理由を正確に言うことはできませんが、ブラウザーがbodyタグでCSSを検索せず、ペイントを開始し、body CSSに遭遇してから、再ペイントしたと思います。

再描画はCSSの影響を受けますか?

正直なところ、JSによる塗り直しがもっと心配です。ただし、DOMが非常に大きい場合は、位置がおかしいためにリフローが発生しないようにCSSを構造化するのが理にかなっています。 @Mattは、その問題をカバーするいくつかの良いリンクを提供しました。いくつかの良いリソース:

http://www.dayofjs.com/videos/22158462/web-browsers_alex-russel Alex Russellが、WebkitがCSSを解析する方法、リフローとリペイントがどのように機能するか、そして何について、約36分間詳細に説明します。それらをトリガーします。

http://code.google.com/speed/page-speed/docs/rendering.html これはCSSレンダリングを最適化する方法に関する基本的な記事です

9
Moses

マークされた答えについてはよくわかりません。私はそれが正しいとは思えません。このように Google Developersからのリンク ブラウザは最初にHTMLファイルをダウンロードし、外部リソースにリンクされたCSSファイルを見つけると、CSSファイルのダウンロードを開始すると同時に、指定されたHTMLファイルのDOM構造を作成しますCSSはDOMに影響を与えないためです。ブラウザがCSSファイルをダウンロードしているときは、ドキュメントにスタイルが適用されないことに注意してください。

CSSファイルをダウンロードした後(スクリプトファイルがないと仮定)、DOMの構築が完了すると、ブラウザーはCSSプロパティをDOMツリー内のそれらのノードにマッピングし始めます。この後、レンダリングツリーと呼ばれる別のツリーが作成され、長方形のボックスとして表示されるすべてのオブジェクトが作成されます。レンダリングツリーが完了した後でのみ、画面へのペイントが開始されます。

要約する:

  • ブラウザはCSSファイルを完全にダウンロードします。
  • ブラウザは、ダウンロード時にページにスタイルを適用しません。ダウンロードが完了すると、ルールのマッピングが開始されます。
  • ルールは、レンダーツリーの構築段階でのみ適用されます。
  • CSSファイルをダウンロードしても、HTMLのダウンロードはブロックされません。ブラウザに注意する必要があります

最初にすべてのhtmlファイルをダウンロードし、次にスタイルファイルとスクリプトファイルをダウンロードします。

Chromeの開発者コンソールを使用してこれらを確認できます。これらすべてを表示するには、[タイムライン]タブを使用します。

タイムライン画像のサンプルを示します ここ 。この回答の冒頭に投稿したリンクはすべてを説明しています。

1
Pragatheeswaran