CSSを遅延読み込みさせてサイトの表示速度を高速化する方法!rel=”preload”とmedia=”print”の使い分け方

11 min 80 views

CSSのせいでサイトの表示速度が遅くなっていませんか?

CSSの遅延読み込みという技術を使えば、その問題を解決できます。

この記事では、landinghubの担当者として、実際にサイトの表示速度を大幅に改善した経験をもとに、CSS遅延読み込みの全てを詳しく解説します。

CSSの遅延読み込みとは?(非同期読み込み)

CSSファイルを非同期で遅延読み込みすることで、HTMLの解析とレンダリングをブロックすることなく、ページの初期表示を高速化できる技術です。

プリロード(rel=”preload”)という方法や、メディアプリント(media=”print”)という方法を使用してCSSを遅延読み込みさせ、JavaScriptでメディア属性を変更する手法が一般的です。

これにより、ユーザーは画面の表示を待つ時間が短縮され、サイトの表示速度改善によるユーザー体験が向上します。

特に大きなCSSファイルや外部フォントを含む場合に効果的で、First Contentful Paint(FCP)の改善が期待できます。

CSSの遅延読み込みの仕組みについて

CSSの遅延読み込みがどのように動作するのか、ブラウザの処理フローを見ながら理解していきましょう。

CSSの遅延読み込みの流れ(非同期読み込み)
  1. クリティカルCSS:ファーストビューに必要なCSSのみをインライン化
  2. 非クリティカルCSS:その他のCSSは後から非同期で読み込み
  3. バックグラウンドでその他のCSSを読み込み、必要に応じて適用
  4. ユーザーは重要な部分をすぐに閲覧可能

①ファーストビューに必要なCSSのみをインライン化

まず最初のステップでは「クリティカルCSS」と呼ばれる、ページの初期表示(ファーストビュー)に必須のスタイルだけを<head>タグ内に直接記述します。

これにより外部CSSファイルのダウンロードを待つ必要がなく、重要なスタイルがすぐに適用されます。

ソース例

<head>
  <style>
    /* クリティカルCSS - 初期表示に必須のスタイルのみ */
    header { background: #0066cc; color: white; }
    .hero { font-size: 2rem; margin-top: 20px; }
  </style>
</head>

②その他のCSSは後から非同期で読み込み

次に、初期表示に必須ではないその他のスタイル(非クリティカルCSS)は、以下のような手法で非同期に読み込みます。

ソース例

<!-- media="print"を使用した非同期読み込み -->
<link rel="stylesheet" href="non-critical.css" media="print" onload="this.media='all'">

<!-- あるいはpreloadを使った非同期読み込み -->
<link rel="preload" href="non-critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'">

<!-- JavaScript fallback -->
<noscript><link rel="stylesheet" href="non-critical.css"></noscript>

③バックグラウンドでその他のCSSを読み込み、必要に応じて適用

最後に、非同期で読み込まれた非クリティカルCSSがバックグラウンドで完全に読み込まれると、それらが適用され、ページの完全なスタイリングが完成します。

これには、アニメーション、詳細なレイアウト、フォールドアウト(画面下部)のコンテンツのスタイルなどが含まれます。

④ユーザーは重要な部分をすぐに閲覧可能

クリティカルCSSが適用された状態でページが表示されるため、ユーザーは重要なコンテンツ(ヘッダー、ナビゲーション、メインのヒーロー部分など)をすぐに閲覧できるようになります。

この段階では、下部のコンテンツやセカンダリーなスタイルはまだ完全に適用されていないかもしれませんが、ページの主要な情報とインタラクションは利用可能です。

通常のCSSの読み込まれる仕組み(同期読み込み)

通常のCSSは、読み込みが終わるまでレンダリングをブロックする同期読み込みになっています。

そのため、たくさんのCSSを読み込んだり、容量の大きいCSSを読み込むとレンダリングが始まらず画面が白い状態が長くなるレンダリングブロックが発生します。

下記はCSSによるレンダリングブロックされている場合の表示例です。

このように、先にCSSが読み込まれてしまうためテキストや画像の表示が遅くなります。

通常のCSSのソース例

<link rel="stylesheet" href="styles.css">

下記は通常のCSSが読み込まれる仕組みを図にしてみました。

CSSの読み込まれる流れ(同期読み込み)
  1. ブラウザheadタグ内のCSSをダウンロードする
  2. CSSをパースし、スタイルコンテキストツリーを作成
  3. HTMLをパースし、DOMツリーを作成
  4. DOMにスタイルを適用し、レンダリング

①ブラウザheadタグ内のCSSをダウンロードする

まず、ブラウザがHTMLドキュメントを読み込むと、<head>タグ内の<link rel="stylesheet">要素を発見し、CSSファイルのダウンロードを開始します。

この段階では、HTMLの解析は続行されますが、レンダリングはCSSが利用可能になるまでブロックされます。

②CSSをパースし、スタイルコンテキストツリーを作成

CSSファイルのダウンロードが完了すると、ブラウザはCSSをパースして、スタイルルールの階層構造である「スタイルコンテキストツリー(CSSOM)」を構築します。

これにより、どの要素にどのスタイルを適用するかの情報が整理されます。

③HTMLをパースし、DOMツリーを作成

HTMLのダウンロードと解析が完了すると、ブラウザは文書のすべての要素と関係性を表現する「DOMツリー」を構築します。このツリーはウェブページの構造を表します。

④DOMにスタイルを適用し、レンダリング

最後に、ブラウザはDOMツリーとスタイルコンテキストツリーを組み合わせて「レンダーツリー」を作成し、画面上に視覚的な表示を行います。

この段階で初めてユーザーはスタイル適用済みのページを見ることができます。

CSSの遅延読み込みの実装方法

それでは、実際にCSS遅延読み込みを実装する方法を見ていきましょう。

いくつかの方法がありますが、ここでは最も効果的な手法を紹介します。

①rel=”preload”を活用したCSSの非同期読み込み

「rel=”preload”」を活用し、非同期で読み込むことができます。

onload属性で読み込みが完了したあとに「rel=”stylesheet”」に変えることでCSSを画面に適用させる仕組みです。

Chromium系のブラウザではリクエストプライオリティは通常の読み込みと同様に最高になるので、非同期にしつつ他のリクエストよりも優先度を高くしたいときに選択します。

下記は「rel=”preload”」を活用したサイト表示例です。

ソース例

<link
  rel="preload"
  as="style"
  onload="this.onload=null;this.rel='stylesheet'"
  href="./style.css"
/>

②media=”print”を活用したCSSの非同期読み込み

「media=”print”」を指定することで印刷用のCSSであるとブラウザに誤認させる方法です。

この方法では非同期の読み込みになります。

onload属性で読み込みが完了したあとに「media=”all”」にすることでWebページ閲覧時に必要なCSSであると認識させ、画面に適用させる仕組みです。

リクエストプライオリティは最低になるので、ボタンを押してから表示されるような必要とされる可能性の低いCSSの読み込み方法として選択します。

下記は「media=”print”」を活用した表示例です。

ソース例

<link
  rel="stylesheet"
  media="print"
  onload="this.media='all'"
  href="./style.css"
/>

③JavaScriptを使ったCSSの非同期読み込み

JavaScriptを使って<link>要素を作成して読み込むことで非同期にする方法です。

記述は増えますが、読み込みの開始タイミングを細かくコントロールできます。

リクエストプライオリティは通常の読み込みと同様に最高になります。

下記はJavaScriptを使った表示の事例です。

ソース例

<script>
  (() => {
    const linkElement = document.createElement('link');
    linkElement.rel = 'stylesheet';
    linkElement.href = './style.css';
    document.head.appendChild(linkElement);
  })();
</script>

また、上記の方法以外にもファーストビューの読み込みが完了してからCSSの読み込みを開始するといった応用もできます。

下記がその表示例となります。

ソース例

<div id="fv">
  <img src="./images/boat.png" alt="" />
  <img src="./images/hut.png" alt="" />
  <img src="./images/bumblebee.png" alt="" />
</div>

<script>
  (async () => {
    const imageElements = document.querySelectorAll('#fv img');

    // ファーストビューの画像が読み込まれるまで待機する
    await Promise.all(
      [...imageElements].map(imageElement => {
        return new Promise(resolve => {
          if (imageElement.complete) {
            return resolve();
          }

          imageElement.onload = resolve;
          imageElement.onerror = resolve;
        });
      }),
    );

    const linkElement = document.createElement('link');
    linkElement.rel = 'stylesheet';
    linkElement.href = './style.css';
    document.head.appendChild(linkElement);
  })();
</script>

CSSの遅延読み込みの実装方法別の特徴

CSSも実装方法によってそれぞれ特性が異なります。

下記のように表で特徴を比較してみました。

同期/非同期読み込み開始タイミングプライオリティ
通常同期即時最高
rel=”preload”非同期即時最高
media=”print”非同期即時最低
JavaScript非同期任意最高

通常の読み込みは同期的で即時に最高優先度で処理されますが、レンダリングをブロックします。

「rel=”preload”」は非同期で即時に最高優先度ながらブロックを回避し、「media=”print”」は非同期・即時ですが最低優先度で表示速度を向上させます。

JavaScript経由の読み込みは非同期で読み込み開始タイミングを制御可能、最高優先度で処理されます。

サイトの要件に合わせた適切な読み込み方法の選択が重要です。

rel=”preload”のおすすめな使い方

「rel=”preload”」のおすすめの活用シーン
  • 重要だが即時には必要ないCSSファイル
  • フォント定義など後から適用しても問題ないリソース
  • パフォーマンスを重視するサイト
  • First Contentful Paint(FCP)を改善したい場合

高優先度でありながら非同期読み込みが可能なため、上記のような活用シーンにおすすめです。

実装が複雑になる場合がややデメリット。

media=”print”のおすすめな使い方

「media=”print”」のおすすめの活用シーン
  • ユーザーエクスペリエンスを優先するサイト
  • フォールドダウン(画面下部)のコンテンツに関するCSS
  • 見た目の整形に関わるが初期表示には影響しない装飾的なスタイル
  • アニメーションやホバーエフェクトなど

 最も簡単に実装できる非同期読み込み方法ではありますが、優先度が低いため適用が遅れる可能性があるのも特徴。

JavaScriptのおすすめな使い方

JavaScriptによる読み込みのおすすめの活用シーン
  • ユーザーインタラクション後に必要になるスタイル
  • 条件付きで読み込みたいCSS
  • 遅延読み込みを細かく制御したい場合
  • SPAなどの動的アプリケーション
  • A/Bテストでスタイルを切り替える場合

読み込みタイミングを完全にコントロール可能なポイントがメリットとして挙げられます。

JavaScriptに依存するためJSが無効な環境では機能しない部分はデメリットな点です。

クリティカルCSSの最適化の方法

クリティカルCSSとは、ウェブページの「ファーストビュー」(ユーザーが最初に見る画面領域)のCSSだけインラインCSSとして書き込んでおいて「ファーストビュー以外」のCSSは外部ファイルとして非同期で読み込むという方法になります。

クリティカルCSSで抽出する

まずは、ファーストビューで表示させる部分のCSSの抽出をツールを使って行います。

色々なツールがありますが、ここではCritical Path CSS Generatorを使った抽出方法をお伝えします。

まずNode.jsとnpmがインストールされていることを確認し、ターミナルでCritical Path CSS Generatorをグローバルインストールします。

    Copynpm install -g critical-path-css-generator
    
    1. ターゲットウェブサイトのURLを指定して実行し、出力をファイルに保存します:
    Copycritical-path-css-generator https://example.com > critical.css
    
    1. オプションを使用してビューポートサイズを調整できます:
    Copycritical-path-css-generator --width=375 --height=667 https://example.com > critical-mobile.css
    
    1. 生成されたクリティカルCSSをHTMLのheadタグ内にインライン化し、残りのCSSは非同期で読み込むように設定します。これにより、初期表示に必要な最小限のCSSを即座に適用しつつ、ページの読み込み速度を大幅に改善できます。

    2. Chrome DevToolsのCoverageタブ

    Chrome DevToolsのCoverageタブを使用すると、どのCSSが実際に使用されているかを確認できます:

    1. DevToolsを開く(F12)
    2. Ctrl+Shift+Pでコマンドパレットを開く
    3. 「Coverage」と入力してCoverageタブを開く
    4. ページをリロードして使用状況を確認

    赤い部分が未使用のCSSなので、これらを遅延読み込みの対象にできます。

    WordPressでの実装例

    WordPressサイトでCSS遅延読み込みを実装する場合の例を紹介します:

    // functions.phpに追加
    add_filter('style_loader_tag', function($tag, $handle, $href, $media) {
        if (is_admin() || did_action('wp_footer')) {
            return $tag;
        }
        
        // クリティカルCSSは除外
        if (in_array($handle, ['my-theme-style'])) {
            return $tag;
        }
        
        // 遅延読み込み用のタグに変更
        $html = '<link rel="preload" href="%1$s" as="style" onload="this.onload=null;this.rel=\'stylesheet\'" data-handle="%3$s" media="%4$s" />
        <noscript>%2$s</noscript>';
        
        return sprintf($html, $href, $tag, $handle, $media);
    }, 10, 4);

    CSSの遅延読み込みを実施するメリット・デメリット

    メリット
    • 表示速度の改善によるUX向上
    • SEO効果の向上
    • サーバー負荷の軽減
    デメリット
    • 実装の複雑さやメンテナンスの手間
    • ブラウザ互換性の問題
    • FOUCの可能性

    メリット

    1. 劇的な表示速度の改善

    CSS遅延読み込みの最大のメリットは、なんといっても表示速度の改善です。実際に測定してみると、First Contentful Paint(FCP)が30〜50%改善されることも珍しくありません。

    landinghub(https://www.landinghub.net/)でも、この技術を活用することで、ランディングページの読み込み速度を大幅に向上させ、コンバージョン率の改善に貢献しています。

    2. ユーザーエクスペリエンスの向上

    ユーザーがサイトを開いた瞬間から、すぐにコンテンツを閲覧できるようになります。これは特にモバイル環境で効果を発揮します。

    3. SEO効果の向上

    Googleは2018年から、モバイルサイトの表示速度を検索順位の要因として考慮しています。CSS遅延読み込みによる高速化は、直接的にSEO効果をもたらします。

    4. サーバー負荷の軽減

    必要なリソースだけを優先的に読み込むことで、サーバーへの負荷も軽減されます。これは特に大量のアクセスがあるサイトで効果的です。

    デメリット

    1. 実装の複雑さとメンテナンスの負担

    CSS遅延読み込みの実装は、通常のCSS読み込みと比較して複雑になります。特に、クリティカルCSSの判別には慎重な検討が必要です。

    サイトの更新やデザイン変更の際に、クリティカルCSSの見直しが必要になる場合があります。定期的なチェックとメンテナンスが求められます。

    2. ブラウザ互換性の問題

    古いブラウザでは、rel=”preload”がサポートされていないため、ポリフィルの使用が必要になります。これにより、実装がさらに複雑になる可能性があります。

    3. FOUCの可能性

    Flash of Unstyled Content(FOUC)と呼ばれる、スタイルが適用されていない状態のコンテンツが一瞬表示される現象が発生する可能性があります。これを防ぐには、クリティカルCSSの選定が重要です。

    CSS最適化の注意点

    段階的な実装アプローチ

    CSS遅延読み込みを実装する際は、いきなり全てのCSSに適用するのではなく、段階的に進めることをお勧めします。

    ステップ1: 分析と計画

    1. 現在のサイトの表示速度を測定
    2. PageSpeed InsightsやGTmetrixで改善点を特定
    3. どのCSSが遅延読み込みの対象になるかを決定

    ステップ2: 小規模テスト

    1. 重要度の低いページから実装開始
    2. 表示崩れや機能不全がないかを確認
    3. パフォーマンスの改善効果を測定

    ステップ3: 本格導入

    1. テストで問題がなければ、メインページに適用
    2. 継続的な監視と調整
    3. 定期的なパフォーマンス測定

    よくある問題とその対策

    1. スタイルの適用遅延

    問題:遅延読み込みしたCSSの適用が遅れ、レイアウトが崩れて見える

    対策:クリティカルCSSにレイアウトに関する基本的なスタイルを含める

    2. JavaScriptエラー

    問題:ポリフィルのJavaScriptでエラーが発生

    対策:最新のポリフィルを使用し、エラーハンドリングを実装

    3. キャッシュの問題

    問題:CSSの変更がブラウザキャッシュにより反映されない

    対策:バージョン番号やハッシュをファイル名に含める

    まとめ

    CSS遅延読み込みは、現代のWebサイトにおいて必須の技術といえます。特に、ユーザーエクスペリエンスとSEOの両方を向上させる効果は絶大です。

    実装は確かに複雑ですが、段階的に進めることで、誰でも導入可能です。まずは小規模なテストから始めて、徐々に全体に適用していくことをお勧めします。

    landinghub(https://www.landinghub.net/)でも、これらの技術を活用してお客様のランディングページを最適化し、コンバージョン率の向上をサポートしています。表示速度の改善でお悩みの方は、ぜひ一度ご相談ください。

    最後に、CSS遅延読み込みは一度設定すれば終わりではありません。サイトの成長や変更に応じて、継続的な最適化が重要です。定期的な測定と調整を行うことで、常に最高のパフォーマンスを維持できます。

    技術は日々進歩しています。今後も新しい最適化手法や標準が登場するでしょう。しかし、「ユーザーに価値を素早く届ける」という基本原則は変わりません。CSS遅延読み込みを通じて、より良いWeb体験を提供していきましょう。

    関連記事

    コメントを残す

    メールアドレスが公開されることはありません。 が付いている欄は必須項目です