Edited at
CSSDay 2

ページ表示を速くするCSSの記述方法

More than 1 year has passed since last update.

今年11月に新しいFirefoxがリリースされましたね。多くの処理がパラレルで動作するようになりマルチコア環境での動作が高速化しました。

この新しいFirefoxで改善された点にCSS描画速度の高速化も含まれていたので、ページ表示速度を速くするためのCSSの記述方法をまとめてみました。


シンプルに適用できるCSSにする(と速くなるはず)

要素への適用ルールをシンプルにできるCSSにすると描画速度が改善されるはず、です。後述しますが、この適用ルールには疑似要素(:beforeや:afterなど)も含まれます。

新しいFirefoxに搭載されているレンダリングエンジンの一部、Quantum CSS (Stylo) は以下3つの要素を組み合わせて実装されています。



  • ServoのParallelism(並行処理)

  • FirefoxのRule Tree

  • ChromeとSafariから取り入れた Style Sharing Cache <- ???

Style Sharing Cacheが何のことか分からなかったので、Mozilla Developer Relations teamのエンジニアによるQuantum CSSの説明を読んでみたStyle Sharing Cacheへの自分なりの理解です。


  • メリット


    • メモリ利用量を抑えられ、描画速度が向上する。



  • 実装方法


    • 事前にCSSセレクタを収集し適用ルールのパターンを作成する。

    • ノード単位で同じルールが適用されていればキャッシュ出来る。



  • 存在するリスク


    • ノードの構造によってはルールが複雑化しキャッシュ効率が下がる。



所々に疑似要素 (Pseudo-elements) の影響があると説明されており、具体的な実装方法が気になりました。

なのでrustで書かれたソースコードを読んでみた所の理解です。


  • Style Sharing Cacheを実現するには以下4つの制約を満たす必要がある。


    • 同じスタイルを継承している事。

    • 同じルールで適用されている事。

    • インラインCSSとプレゼンテーションヒントが同じ事。

    • 疑似要素のルールが同じ事。



  • 疑似要素によって制約を満たすための方法が複雑になっている。

  • 具体的にどのパターンだと適用されないのか?がちょっと不明。

Style Sharing Cacheで行われている事が明確になり理解が進みました。

とりあえず、要素への適用ルールがシンプルなCSS(疑似要素を含む)にするとキャッシュが有効になるので描画速度が速くなるはずです。


レイアウトのCSSトリガーになっているCSSプロパティをCSS Triggers.comで確認する

ウェブページの描画は「レイアウト > ペイント > 合成」の関係が成り立ちます。

レイアウトのトリガーになるCSSプロパティを変更すると、レイアウトからの再描画(ドキュメント全体に影響する)が発生し描画速度が遅くなります。

レイアウトのCSSトリガーとなっていないCSSプロパティを優先して利用するようにすると、レイアウトからの再描画を回避できます。

え、そんな事を言われても、一体どれがトリガーになっているの?となりますよね。

CSSトリガーとなっているCSSプロパティの一覧はCSS Triggers.comで確認できます。各レンダリングエンジン別で確認できるので便利です。

1つ例を挙げると、比較的利用頻度の高いbackground-imageはBlinkとGeckoでは「ペイント > 合成」のためレイアウト変更が発生しませんが、WebkitとEdgeHTMLでは「レイアウト > ペイント > 合成」となりレイアウトの変更が発生します。

このレイアウトの問題は大きく複雑なレイアウトとレイアウト スラッシングの回避で詳細に説明されています。


floatよりもflexboxを利用する

floatと比べflexboxはレイアウトの処理時間を短くできます。

そのため昔から利用されているfloatを利用したレイアウト調整よりも、新しいブラウザで実用化され始めたflexboxを利用した方がページのレンダリングが速いです。

flexboxを使うデメリットとしては(挙動が安定しつつありますが)予期せぬ現象への対処に時間が取られる所でしょうか。


CSS内でリソース読み込みを避ける(webfontのimportなど)

これは良く話題になるため意識している方も多いと思います。URL先の読み込みが優先されてパラレルに動作しなくなります。

@import url('https://fonts.googleapis.com/css?family=Open+Sans');

この解決方法はCSS内で行っているリソースの読み込みをHTML上に移動する事です。

<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Open+Sans" />

さらに速くするにはbase64エンコーディングして埋め込んでしまいます。

@font-face {

font-family: 'Open Sans';
src:url("data:font/ttf;base64,AAEAAAASAQA[...]") format('truetype');
}


まとめ

CSSの最適化はページ表示の高速化を行う中でも後回しにされる事が多いですよね。CSSを書き直すの大変ですし。

ただ動作速度もUI/UXに影響するので暇な時に見直してみると改善点が見つかるかも知れません。