画面の表示速度を意識してCSSを書こう
WEBページの表示速度を高速に保つことでサイトの直帰率を防げたりSEO上の観点でも有利に働くことはよく知られている事実かと思います。
2018年2月に更新されたGoogleのダニエル・アンによる研究結果ではスマホページにおいてloadingタイムが1秒から5秒に増えると直帰率は90%増加するそうです。
表示速度を早める方法はサーバーサイド側での改善など多くの手法がありますが、CSSセレクタを最適化することでWebページの表示速度に貢献できることを知っていますか?
『CSSセレクタの最適化』といった観点でサイトの読み込み速度を上げる方法をご紹介します。
CSSセレクタの照合は左から右?
#main-visual > .main-visual__title {
font-weight: bold;
}
ブラウザがこのコードを左から右へ順にマッチしていくと考えると、このルールはそれほどコストがかからないと思えます。
- ページに一つしかない
main-visual
要素を見つける - その子の
main-visual__title
を見つける - スタイルを適用
正解は...
#main-visual > .main-visual__title {
font-weight: bold;
}
実際にはCSSセレクタは右から左へ照合されます。
-
main-visual__title
を探す - その親要素が
main-visual
かどうかを調べる - スタイルを適用
main-visual
はページに1箇所しかないのがわかっているのに最初に検索するのはmain-visual__title
。
とても効率が悪いですね。レンダリング速度が低下してしまいます。
ちなみに一番右端のセレクタはキーセレクタと呼ばれています。
このことから、キーセレクタに適用範囲が大きいセレクタを指定してしまうと照合するのに時間がかかりそうです。
シンプルに定義しよう
.main-visual__title {
font-weight: bold;
}
ベストプラクティスは対象となるセレクタだけを指定することです。
そうすることによって無駄な検索が行われないので、レンダリング速度の低下を抑えられます。
CSSの書き方NG集
NG①:要素セレクタを組み合わせて使う
ul.menu {
padding-right: 5px;
}
要素セレクタが変更になったときのメンテナンスが面倒にもなります。
クラスセレクタだけで十分です。
.menu {
padding-right: 5px;
}
NG②:複雑な子孫セレクタ
.c-table {
&.c-table--form {
tbody {
tr {
th {
border-top: 1px solid #ffffff;
}
}
}
}
}
ネストが深いぶん照合に時間がかかります。
もっとシンプルにしましょう。
.c-table {
&.c-table--form {
th {
border-top: 1px solid #ffffff;
}
}
}
※要素セレクタのth
ではなくクラスセレクタでも可。
また、modifireのc-table--form
がc-table
のあとに記述されるルールであるならばもっとシンプルに記載できます。
.c-table--form {
th {
border-top: 1px solid #ffffff;
}
}
Bad CSS:Redundant tags selectors(参照)
NG③:ulとliの併用
.menu-wrap {
ul {
li {
border-bottom: 1px solid #cccccc;
}
}
}
<li>
セレクタはほぼ常に<ul>
タグに内包されているので<ul>
の指定を外しましょう。
.menu-wrap {
li {
border-bottom: 1px solid #cccccc;
}
}
Bad CSS:Redundant tags selectors(参照)
NG集はわかったけど、それって本当に遅くなるの?
『続・ハイパフォーマンスWebサイト』に掲載されているサイトを活用し実際に計測してみました。
基準となるHTMLが用意されており、ページごとにCSSのセレクタの指定方法が異なります。それぞれのページにアクセスした際、表示速度がどれくらいになるのかをページ内のpage load time欄に表示してくれます。
Chrome,Firefox,IEで実際にアクセスし、page load timeの数値を記録して表にしました。
測定基準となるHTML
<div>
<div>
<div> <p> <a id='id0001' class='class0001'>0001</a> </p> </div>
...
<div> <p> <a id='id1000' class='class1000'>1000</a> </p> </div>
</div>
</div>
対象CSS
// 未適用
.noclass0001 { background: #CFD; }
...
.noclass1000 { background: #CFD; }
// 要素セレクタ
A { background: #CFD; }
.noclass0001 { background: #CFD; }
...
.noclass1000 { background: #CFD; }
// クラスセレクタ
.class0001 { background: #CFD; }
...
.class1000 { background: #CFD; }
// 子セレクタ
DIV > DIV > DIV > P > A.class0001 { background: #CFD; }
...
DIV > DIV > DIV > P > A.class1000 { background: #CFD; }
// 子孫セレクタ
DIV DIV DIV P A.class0001 { background: #CFD; }
...
DIV DIV DIV P A.class1000 { background: #CFD; }
// ユニバーサルセレクタ
P.pclass0001 * { background: #CFD; }
...
P.pclass1000 * { background: #CFD; }
// 遅めのセレクタ
#id007 > A { ... }
Chrome | Firefox | IE11 | |
---|---|---|---|
未適用(Baseline) | 12 | 26 | 14 |
要素セレクタ(Tag) | 45 | 30 | 28 |
クラスセレクタ(Class) | 44 | 28 | 28 |
子セレクタ(Child) | 102 | 100 | 279 |
子孫セレクタ(Descendant) | 47 | 33 | 13 |
ユニバーサルセレクタ(Universal) | 51 | 29 | 248 |
遅めのセレクタ | 131 | 98 | 121 |
※ChromeはMac Sierra、FirefoxとIE11はWindows7
※キャッシュ削除し単一タブで検証(2018.3.1現在)
ブラウザによって表示速度の大小はあるものの、セレクタの書き方による変化は見て取れました。
ここから判明したことは
- 子セレクタが圧倒的に遅い
- クラスセレクタが一番早い?
- キーセレクタで要素セレクタを指定(上記の遅めのセレクタ)の場合複合セレクタの数に関係なく遅くなる
ということです。
ただこの検証結果の数値は回線速度などの環境による影響を受けやすいので、あくまでも一例として捉えていただければと思います。
その他の表示速度を上げる方法
いままではCSSをどのように書くと表示速度が遅くなるのかを調査しました。
それ以外にもやるべきこととしてCSSファイルサイズを小さくする方法があります。
CSSファイルのサイズを抑えてレンダリング速度をあげよう
CSSファイルのサイズが大きくなると読み込みに時間がかかる原因となり、表示速度に影響を与えてしまいます。
コーダーはファイルサイズをなるべく小さくすることを念頭に置きながら開発する必要があります。
無駄な記述を少なくすることでファイルサイズを小さくし、レンダリング速度に貢献しましょう。
サイトを多角的に分析!
サイトのJSやCSSについて細かく分析してくれるYellow Lab Toolsがあります。GithubのStarが1403あるので多くに支持されているサービスのようです。
こちらのサイトを使って自分の担当サービスの改善点を洗い出してみました!
サービス名を公表できない関係上、ソースコードを一部改変しています。
以下、指摘事項のなかでも特に気になったCSS関連の指摘をピックアップして改善案を提示していきます。
指摘①:複合セレクタを3つ以内にしよう
#header ul li .foo
のように4つ以上のセレクタは表示速度低下を招きます。複合セレクタは3つ以内になるように心がけましょう。
該当箇所が409ありました。
9セレクタを指定しているところもありました
指摘例:
.hogehoge .hugahuga .eeee .mada span.konnani {}
.selector .shiteishiteru:hover .ooina>a .waaaaaaa {}
CSS complexity:Complex selectors(参照)
指摘②:古いベンダープレフィックスを削除しよう
ブラウザのバージョンが常日頃アップされているのに伴い、使われなくなったベンダープレフィックスが残っていました。
-
-moz-box-sizing: content-box
- Firefox28以前
-
-webkit-border-radius: 16px
- Androidブラウザ2.1、Chrome4、iOS Safari3.2 Safari4以前
-
-ms-transform-origin: 0 0
- IE9以前
特に読み込まれているcolorbox.css
で多々指摘されており、それは2016年7月からアップデートされていないようです。
Bad CSS:Old prefixes(参照)
指摘③:ルールの2重記述を見直そう
CSSのルールが2重に記載されている箇所が31箇所ありました。
うまくマージをする必要があります。
例:
.hoge .huga {
float: left;
margin: 0;
width: 70px;
text-align: center;
}
.hoge .huga {
position: relative;
float: left;
margin: 0;
padding-right: 10px;
width: 50px;
text-align: center;
}
Bad CSS:Duplicated selectors(参照)
指摘④:似通ったカラー定義を見直そう
似たようなカラーが散見されるという指摘内容です。
確かにほぼ一緒のカラーがある。。。
主要カラーは変数で定義し管理しているはずだけれども、それ以外で使っているカラーが多く指摘されているようです。
CSS complexity:Similar colors(参照)
指摘⑤:CSSのルールが膨大すぎるので見直そう
CSS | Rule | |
---|---|---|
1 | application.css | 2806 |
2 | xxxxxx_common.css | 1677 |
3 | jquery-ui-1.10.3.custom.min.css | 357 |
4 | xxxxxx_top.css | 307 |
5 | jquery.mCustomScrollbar-3.1.5.css | 254 |
6 | xxxxxx_calendar.css | 119 |
7 | colorbox.css | 24 |
合計 | 5544 |
該当のページでは5544のルールが使われているという結果がでました。圧倒的に多い...
ルールを減らすのを目的とするというよりかは、今までの指摘①~④を修正することによって結果としてファイルサイズが減少するといったところでしょうか。
ルールは750以下にするとスコア100を取れるようです。
コンポーネントをまとめているapplication.css
だけで2806もルールがあるので、750まで抑えるのはなかなか難しいです。ただ357ルールが定義されている jquery-ui-1.10.3.custom.min.css
や254ルールあるjquery.mCustomScrollbar-3.1.5.css
などプラグインとして必要なCSSも膨大なルールが定義されているので、必要なスタイル定義だけを自サイトで管理するようにして不必要なルールを書き込まないような運用も検討したいです。
CSS complexity:Rules count(参照)
まとめ
CSSは簡単にかけて自由度が高いですが、セレクタの指定の仕方一つとっても表示速度に影響するとなると、注意が必要です。特に複数人で開発を行うようなサービスにおいては共通認識がないと表示速度が遅くなるようなCSSが散見されてしまいます。
サイトの表示速度はユーザー離れの要因の一つにもなりかねないので、UX体験を向上させる一つとしてCSSの書き方には注意を払っていきたいですね。
参考
- [GitHubがCSSのパフォーマンス改善のためにおこなったことをまとめたスライド - coliss] (http://coliss.com/articles/build-websites/operation/css/slide-githubs-css-performance-by-jonrohan.html)
- 続・ハイパフォーマンスWebサイト - ウェブ高速化のベストプラクティス - O'Reilly Japan
- [Find out how you stack up to new industry benchmarks for mobile page speed - think with Google] (https://www.thinkwithgoogle.com/marketing-resources/data-measurement/mobile-page-speed-new-industry-benchmarks/)