Sassyブログ

埼玉県在住のシステムエンジニアです。基本的にはIT技術関連の内容を中心に発信していきます。たまにゲーム関連ネタも載せます

レンダリングブロックせずにCSSを非同期的に読み込ませる簡単なテクニック

はじめに

CSSは画面描画をブロックするリソースとして扱われます。

developers.google.com

今回はパフォーマンス改善の一環としてCSSを非同期に読み込ませるテクニックを紹介していきます。

知っている方は結構いるかと思いますので知らない方へ紹介出来たらなと思います!

サイトの表示に時間がかかったりする時に色々なパフォーマンス改善のテクニックがあるかと思います。

例えばJavaScriptを記述する場所はbodyの閉じタグの直前にするとか、async属性やdefer属性を付けるとか。

こうすることでJavaScriptに関してはHTMLのレンダリングをブロックせずに実行させることができます。

ではlinkタグで読み込ませるCSSはheadタグ内でしか記述できません。
JavaScript利用すれば可能みたいですが。)

しかしJavaScriptCSSをbodyの閉じタグの直前で読み込ませたりするのは手間ですし何より可読性が低くなります。

またlinkタグにはscriptタグのようにasyncdefer属性はありません。

さてCSSに関してはどのように改善したらよいでしょうか?

preloadpreconnectのResourse Hintsを使う?

いくつかの解決方法がでてきます。

まずはrel属性を使って、その設定値にpreloadpreconnectを記述することです。

※上記記述の値以外にも設定値があるので以下のResourse Hintsを確認してみてください。

https://w3c.github.io/resource-hints/

しかし、preloadに関しては仕様が安定してないので将来的に動きが壊れる可能性があります。

https://w3c.github.io/preload/

また、preconnectfirefoxでは未サポートとなっており、SafariなどではTP(Technology Preview)となっているため試験的に入っているようです。

Can I use... Support tables for HTML5, CSS3, etc

media属性とonload属性を使った非同期読み込みテクニック

今回紹介するテクニックは以下のmedia属性とonload属性で解決できます。

<link rel="stylesheet" media="print"  onload="this.media='all'" ・・・ />

では実際にどのようなことが起きているのでしょうか?

まずmedia="print"と指定してあげることで、印刷時に適用するCSSであることを宣言します。

この段階では適用するのが印刷時なのでダウンロードのみ行われます。

ロードの実行はレンダリングをブロックしないため非同期で行われます。

そして onload="this.media='all'"が指定されているためロードが完了するとonload属性に記述したthis.media="all"が実行され、linkタグのmedia属性にallが設定されますallが設定されることでブラウザにスタイルが適用されるという仕組みになっています。

こうすることで簡単にレンダリング時のパフォーマンスを上げることができます。

最後に

ただし、何でもかんでも非同期化をすればいいというわけではないので使いどころに関しては実装する際にトレードオフを考えて実装してください。

例えばCSSの適用を遅らせることで画面表示のパフォーマンスは上がりますがアクセス時に一瞬スタイリングされていないHTMLのみのページが表示されてしまい少し不格好になってしまいます。

それであればローディング画面を少し表示してあげて画面レンダリングが完了するのを待ってから表示してあげる方がキレイです。

このテクニックは非常に簡単にできますが、本当に自分たちのプロダクトに適した方法なのかを考えてから使用してもらえればなと思います。