CSSの「:active」はIE(Edge)で重い
データテーブルなど要素が大量にある画面をIEで開いている時、スクロールが妙に重いので調査したところ、ボタンにかけていた擬似要素「:active」の存在が重くしていると分かりました。
「:active」の中のCSSプロパティではなく、「:active」の擬似要素がCSSに存在するだけで重くなっていました。
しかも最新のEdgeバージョンで。
経緯と状況
下記のデモページをIEで開いてみてください。
重さを体感できるようにするため膨大な行のテーブルを overflow:scroll のレイヤーで囲ってますが、中身はどうでもいいです。
クリックしてからすぐスクロールしたり、スクロールバーのツマミからスクロールしようとすると一瞬引っかかると思います。これは「:active」が原因でIE内でCPU使用率が高まっているためです。
下図はIEのDevツールでUIの応答速度を計測したものです。
赤枠を付けてる箇所はクリックした時に発生した処理です。
クリックごとに「スタイル指定」の処理が1秒ほど走っているのですが、その詳細を見ると<body>から始まり全てのタグを走査していました。HTMLタグが多いほどチリツモで重くなっている状態です。
最初はこれがなぜ発生しているのかが理解できず、JSとCSSの両方でシラミ潰ししていました。
原因の「:active」について
デモページでは下記のCSSを設定しています。
.btn:active { }
中身のプロパティはどうでもよく、.btn 自体もHTMLの中で使っておらず、「:active」がCSSの中に存在することで重さを引き起こしています。
そこで下記のように a タグのセレクタを明示的に書きます。
a.btn:active { }
そうすると重さが解消されます。
UIの応答速度計測でも、クリックしした時の走査処理が無くなっています。
明示的にタグを指定したのでaタグ以外で走査しなくなったからと思えたのですが、下記のようにaタグ以外を指定するとまた重くなってしまいました。明示的な指定かどうかは関係ないと分かります。
input.btn:active { }
ここで思い当たるのがCSS2とCSS3による仕様の違いです。
「:active」の擬似要素はCSS2ではaタグのみに使え、CSS3からはあらゆるタグに使えるようになりました。
その経緯を考えると、あくまで推測ですがIEのレンダリングはCSS2の仕様のまま、力技でCSS3の振る舞いをしているのではと思えます。つまり、IEが「なんちゃってCSS3」をやってるのが原因。
デモページはタグの量を増やすため膨大なテーブルで組みましたが、事の発端は文字やinputなど要素の多い100行程度のテーブルだったので、行数ではなくタグの量に比例して重くなるのでテーブルに限った話でもありません。
対策
- 「:active」をCSSから排除して問題なければ排除する。
- 表現上排除できないなら「:active」は排除して同様の処理をJSでやる。
Gmailなんかはソース見た感じ、この問題を把握しているのか「:active」に頼らずJSでのクラスのトグルして表現を切り替えてます。
とりあえずな、Edge(笑)って何だよ。おまえいい加減にしろよ。
IE開発者はタンスの角に小指ぶつけてSHINE(輝け)
筆者について

- ゲームとジョジョを愛するファミッ子世代。好きな言葉は「機能美」。
公私ともにWebサービスを作る系男子。
最近の投稿
運用2017.03.03nginxのkusanagiにLet’sEncryptをかけてるとiOSで表示されない問題の解決
運用2016.07.22分かりにくい「クリエイティブコモンズ」をシンプルに言うと
WordPress2016.07.12新しいWordPress「Calypso」を試した
Design2016.03.09Win10アプリのデザインガイドラインが素晴らしい