ホームページ  >  記事  >  ウェブフロントエンド  >  Web ページのレンダリングについて、フロントエンド担当者が知っておくべきこと_html/css_WEB-ITnose

Web ページのレンダリングについて、フロントエンド担当者が知っておくべきこと_html/css_WEB-ITnose

WBOY
WBOYオリジナル
2016-06-21 08:46:571189ブラウズ

ブラウザはどのように Web ページをレンダリングしますか?

ブラウザがページをレンダリングする動作から始めましょう:

  • サーバーから取得した HTML ドキュメントから DOM ツリー (ドキュメント オブジェクト モデル) を構築します。 >

  • スタイルが読み込まれて分析され、CSSOM (CSS Object Model) が構築されます。

  • DOM と CSSOM に基づいてドキュメント ツリーが構築されます。一連のオブジェクトがレンダリングされます (Webkit ではそれぞれを「レンダラー」または「レンダー オブジェクト」と呼び、Gecko では「フレーム」と呼びます)。レンダー ツリーには、非表示の要素 (93f0f5c25f18dab9d176bd4f6de5d30e、display:none) を除くすべての要素が反映されます。外部 DOM 構造内のすべての表示要素と文字列は、レンダリング ツリー内の独立したレンダリング オブジェクトとして扱われます。各レンダリング オブジェクトは、対応する DOM 構造と計算されたスタイルの混合物です。つまり、レンダリング ツリーは DOM の視覚的表現です。 Tree;

  • 各レンダリング ツリー要素の座標が計算によって取得されます。これをレイアウト (レイアウト) と呼び、ブラウザーはドキュメント ウェイ (つまり、レイアウト) を介して流れます。すべての要素は一度に完了できます) (テーブルには複数のレイアウトが必要です);

  • 最終的なレンダリング ツリーがブラウザ ウィンドウに表示されます。このプロセスはペイントと呼ばれます。

ユーザーがページを操作するか、スクリプトが変更されると、ドキュメント構造の変更により、上記の手順の一部が再実行されます。

再描画

要素スタイルの変更が Web ページ上の要素の位置 (背景色、境界線の色、可視性) に影響しない場合、ブラウザは新しいスタイルを適用するだけです。要素に。

リフロー

リフロー (再レイアウト) は、変更が

ドキュメントのコンテンツや構造、要素の位置 に影響を与える場合に発生します。これは通常、以下によって引き起こされます:

  • DOM 操作 (要素の追加、削除、変更、または順序の変更);

  • コンテンツの変更 (テーブル領域内のテキストの変更を含む) ) (占有位置サイズが変更されました);

  • CSS プロパティを計算または変更します (位置変更);

  • スタイル シートを追加または削除します。 >

  • クラス属性の変更 (位置が変更される場合があります);
  • ブラウザ ウィンドウの操作 (サイズ変更、スクロール);
  • 疑似クラスのアクティブ化 (位置が変更される可能性があります)
  • ブラウザーがレンダリング メカニズムを最大限に活用する方法

ブラウザーは次のように制限されます。変更された要素が配置されている領域の再配置と再描画が可能です。たとえば、display:fixed/absolute 要素が変更されると、それ自体とその子要素にのみ影響しますが、display:static 要素が変更されると、後続のすべての要素に影響します。要素は再描画されます (できるだけ少ない要素に影響します)

パフォーマンスを最大化するためのもう 1 つのメカニズムは、一連の JavaScript スニペットを実行するときに、ブラウザーがそれらをキャッシュしてからすべてを一度に実行することです。次の例を見るとよく理解できます:

ただし、すでに上で述べたように、
var $body = $('body');$body.css('padding', '1px'); // reflow, repaint$body.css('color', 'red'); // repaint$body.css('margin', '2px'); // reflow, repaint// only 1 reflow and repaint will actually happen(由于缓存,只会重绘一次)

したがって、2 つのリフローが発生するため、パフォーマンスを最大化するために要素の属性を読み取るために結合する必要があります。

var $body = $('body');$body.css('padding', '1px');$body.css('padding'); // reading a property, a forced reflow(强制发生)$body.css('color', 'red');$body.css('margin', '2px');//另外一次reflow

場合によっては、例: マージン左を同じオブジェクトに 2 回適用する必要があります。最初はアニメーションなしで 100 ピクセルに設定され、次にアニメーションによって 50 ピクセルに遷移します。
$(function() {  var $body = $('body');  $body  .on('click', '.block-1', function(e) {    // 1 reflow        $body.css('padding', '1px');    $body.css('color', 'red');    $body.css('margin', '2px');  })  .on('click', '.block-2', function(e) {    // 2 reflows        $body.css('padding', '1px');    $body.css('padding');    $body.css('color', 'red');    $body.css('margin', '2px');  })  .on('click', '.block-3', function(e) {    // 3 repaints        $body.css('color', 'red');    $body.css('color');    $body.css('color', 'yellow');    $body.css('background');    $body.css('color', 'blue');    $body.css('outline');  })  .on('click', '.block-4', function(e) {    // 1 repaint        $body.css('color', 'red');    $body.css('color', 'yellow');    $body.css('color', 'blue');    $body.css('color');    $body.css('background');    $body.css('outline');  })  .on('click', '.block-5', function(e) {    // 3 reflows        $body.css('padding', '1px');    $body[0].offsetHeight;    $body.css('padding', '2px');    $body[0].offsetTop;    $body.css('padding', '3px');    $body[0].offsetWidth;  })  .on('click', '.block-6', function(e) {    // 1 reflow        $body.css('padding', '1px');    $body.css('padding', '2px');    $body.css('padding', '3px');    $body[0].offsetHeight;    $body[0].offsetTop;    $body[0].offsetWidth;  });});

トランジション アニメーション:

プロセス コード:
.has-transition {   -webkit-transition: margin-left 1s ease-out;      -moz-transition: margin-left 1s ease-out;        -o-transition: margin-left 1s ease-out;           transition: margin-left 1s ease-out;}

変更がキャッシュされて最後に実行されるため、上記のコードは期待どおりに動作しません。一度、今度は強制実行が必要です。 :

// our element that has a "has-transition" class by defaultvar $targetElem = $('#targetElemId');// remove the transition class$targetElem.removeClass('has-transition');// change the property expecting the transition to be off, as the class is not there// anymore$targetElem.css('margin-left', 100);// put the transition class back$targetElem.addClass('has-transition');// change the property$targetElem.css('margin-left', 50);
期待した効果を達成するコード

これで期待した効果が得られました。

// remove the transition class$(this).removeClass('has-transition');// change the property$(this).css('margin-left', 100);// trigger a forced reflow, so that changes in a class/property get applied immediately$(this)[0].offsetHeight; // an example, other properties would work, too// put the transition class back$(this).addClass('has-transition');// change the property$(this).css('margin-left', 50);
パフォーマンスの最適化に関する提案

いくつかの役立つ情報を要約したこの記事には、次の提案があります

有効な HTML と CSS を構築することを忘れないでください。ドキュメントのコーディング メソッドを宣言します。スタイル シートは 93f0f5c25f18dab9d176bd4f6de5d30e タグに含める必要があり、スクリプト ファイルは
  • タグの最後に配置する必要があります。 CSS セレクターを簡略化して最大限に活用する (この記事は、CSS プリプロセッサを使用するほとんどの開発者によって無視されます)、維持管理が最も少ない階層構造です。以下は各セレクターの効率ランキングです
  • #id.classdiva+iul>li*input[type='text']a:hover
    ブラウザはセレクターを右から左に読み取るので、一番右のセレクターはより効率的な #id,.class を選択する必要があることに注意してください
div * {...} // bad.list li {...} // bad.list-item {...} // good#list .list-item {...} // good
  • 在脚本中,应该尽可能的减少DOM操作,如果对象和属性会被重用,就缓存它们。在最好离线元素(未被插入文档树)(offline)上进行操作,然后把它插入DOM结构中;

  • 如果使用jQuery,遵循[jQuery选择器基本原则( http://learn.jquery.com/performance/optimize-selectors/);

  • 修改元素的样式时,修改class属性是做好的方法,其位置越深,越好(also because this helps decouple logic from presentation);

  • 只使 display:fixed/absolute的元素具有动画;

  • 不适用复杂的 :hover动画也是一个好的实践(给 6c04bd5ca3fcae76e30b72ad730ca86d添加 no-hover属性), 延展阅读;

延展阅读已获得更多信息:

  1. How browsers works;

  2. Rendering: repaint, reflow/relayout, restyle;

希望这边译文对您有用

原文链接

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。