Edited at

<CSS>サイトの表示速度を意識したセレクタの書き方

More than 1 year has passed since last update.


画面の表示速度を意識してCSSを書こう

WEBページの表示速度を高速に保つことでサイトの直帰率を防げたりSEO上の観点でも有利に働くことはよく知られている事実かと思います。

2018年2月に更新されたGoogleのダニエル・アンによる研究結果ではスマホページにおいてloadingタイムが1秒から5秒に増えると直帰率は90%増加するそうです。


think with Google


表示速度を早める方法はサーバーサイド側での改善など多くの手法がありますが、CSSセレクタを最適化することでWebページの表示速度に貢献できることを知っていますか?

『CSSセレクタの最適化』といった観点でサイトの読み込み速度を上げる方法をご紹介します。


CSSセレクタの照合は左から右?


#main-visual > .main-visual__title {
font-weight: bold;
}

ブラウザがこのコードを左から右へ順にマッチしていくと考えると、このルールはそれほどコストがかからないと思えます。

1. ページに一つしかない main-visual 要素を見つける

2. その子の main-visual__title を見つける

3. スタイルを適用


正解は...


#main-visual > .main-visual__title {
font-weight: bold;
}

実際にはCSSセレクタは右から左へ照合されます。

1. main-visual__title を探す

2. その親要素が main-visual かどうかを調べる

3. スタイルを適用

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--formc-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

http://stevesouders.com/efws/css-selectors/baseline.php


※ChromeはMac Sierra、FirefoxとIE11はWindows7

※キャッシュ削除し単一タブで検証(2018.3.1現在)


ブラウザによって表示速度の大小はあるものの、セレクタの書き方による変化は見て取れました。

ここから判明したことは


  • 子セレクタが圧倒的に遅い

  • クラスセレクタが一番早い?

  • キーセレクタで要素セレクタを指定(上記の遅めのセレクタ)の場合複合セレクタの数に関係なく遅くなる

ということです。

ただこの検証結果の数値は回線速度などの環境による影響を受けやすいので、あくまでも一例として捉えていただければと思います。


CSSファイルのサイズを抑えてレンダリング速度をあげよう

CSSファイルのサイズを小さくすることでもレンダリング速度をあげることができます。

無駄な記述を少なくすることでファイルサイズを小さくし、レンダリング速度に貢献しましょう。


サイトを多角的に分析!

サイトのJSやCSSについて細かく分析してくれるYellow Lab Toolsがあります。GithubのStarが1403あるので多くに支持されているサービスのようです。

こちらのサイトを使って自分の担当サービスの改善点を洗い出してみました!

サービス名を公表できない関係上、ソースコードを一部改変しています。

以下、指摘事項のなかでも特に気になったCSS関連の指摘をピックアップして改善案を提示していきます。


指摘①:複合セレクタを3つ以内にしよう

#header ul li .foo のように4つ以上のセレクタは表示速度低下を招きます。複合セレクタは3つ以内になるように心がけましょう。

該当箇所が409ありました。

9セレクタを指定しているところもありました:disappointed_relieved:

指摘例:


.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箇所ありました。

うまくマージをする必要があります。

例:


xxxxxx_top.scss/L985

.hoge .huga {

float: left;
margin: 0;
width: 70px;
text-align: center;
}


xxxxxx_top.scss/L1026


.hoge .huga {
position: relative;
float: left;
margin: 0;
padding-right: 10px;
width: 50px;
text-align: center;
}


Bad CSS:Duplicated selectors(参照)



指摘④:似通ったカラー定義を見直そう

似たようなカラーが散見されるという指摘内容です。

確かにほぼ一緒のカラーがある。。。

主要カラーは変数で定義し管理しているはずだけれども、それ以外で使っているカラーが多く指摘されているようです。

image.png


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の書き方には注意を払っていきたいですね。


参考