クリティカルCSSとは何か?
クリティカルCSSとは、WEBページの読み込み速度を改善するためのテクニックです。
ブラウザがページを読み込むときに、CSSの読み込みに時間がかかって、画面の読み込みが遅れてしまうことがあります。
これを防ぐためにクリティカルCSSでは以下のようなことをします。
こうすることで、ページのURLをクリックしたときに、ユーザーが最初に目にする部分のコンテンツを通常よりも早く表示することができます。
なお、ブラウザがソースコードを読み込んでページを表示する処理を「レンダリング」といいます。このため「レンダリングブロックを改善する」といった言われ方もします。
なぜページの読み込みに時間がかかるのか?
CSSは通常headタグの中にlinkタグを記述して読み込みます。
ブラウザはlinkタグで指定されているファイルの内容を全て読み込んでから、次のコードを読み込むように動作します。
これは、逆にいうと、linkタグで指定で指定されているファイルの内容を全て読み込むまでは、他のコードの読み込みがストップするということです。
HTMLの例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./style.css">
<title>Document</title>
</head>
<body>
</body>
</html>
例えば上記の例だと、linkタグのところで「style.css」を読み込むときに、その中の記述が重いと、その内容を全て読み込むまで、その下のコードの読み取りに以降しません。
ページ速度読み込みの改善がなぜそれほど重要なのか?
ページの表示速度が遅いとユーザビリティーが悪くなるのは当然です。
Googleが行った調査ではページの表示に3秒かかると約30%の人が、ページを見るのをやめて他のページに移動してしまうという結果がでています。
そして、Googleはユーザビリティを向上するために、ファーストビューの表示速度が遅いページの検索結果の順位を下げるアルゴリズムを取り入れています。
このため、SEO対策として、ファーストビューのページ表示速度を改善することが非常に重要となっています。
例えば、Page Speed Insightというページの表示速度を計測するツールで確認すると、First Contentful Paintといった指標があります。
これは、ユーザーがURLをクリックしてからページが表示されるまでの時間です。この速度が遅いとSEOスコアが下がります。
クリティカルCSSの実装例
例えば、PHPを使ったプロジェクトでクリティカルCSSを実装するためには、headタグの中に以下の記述を使って、スタイルシート(.css)の内容を直接表示します。
<head>
省略
<style type="text/css">
<?= file_get_contents(CSSのファイルパス) ?>
</style>
省略
</head>
<?= ?>
は<?php echo ?>
の省略形で、指定した変数や処理結果をそのまま表示します。
file_get_contents()メソッドは、指定したファイルの内容を呼び出す処理です。
クリティカルCSSの実例
上記のfile_get_contentsメソッドを使って、プロジェクトで実際にクリティカルCSSを実装する方法を紹介します。
実装手順は大きく以下の3ステップになります。
headタグの中に直接表示するファイルの準備
最初に、ファーストビューで使用するスタイルのみを記述した、ファイルを用意します。
ここでは以下のようなディレクトリパスにファイル「mainview.css」を作成します。
「public > css > mainview.css」
ファイル名に特に指定はありません。ここでは、ファーストビューやメインのコンテンツ用のCSSをまとめるので、mainview.cssとします。
linkタグで読み込むファイルの準備
続いて、ファーストビューやメインのコンテンツで使用するスタイル以外のスタイルをまとめたCSSファイルを作成します。
mainview.cssと同じディレクトリに、bottomview.cssを作成します。
「public > css > bottomview.css」
ファイル名に特に指定はありません。ここでは、ファーストビューやメインのコンテンツ用のCSS以外の下部のコンテンツ用のスタイルをまとめるので、bottomview.cssとします。
PHPファイルで読み込み
上記で作成したファイルをそれぞれ、ファーストビューやメインのコンテンツ用のmainview.cssはheadタグの中のstyleタグの中に、file_get_contentsを使って直接読み込みます。
bottomview.cssはbody閉じタグのすぐ上でlinkタグを使って読み込みます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style type="text/css">
<?= file_get_contents( 'mainview.cssへの絶対パス' ); ?>
</style>
</head>
<body>
<link href="bottomview.cssへの相対パス" rel="stylesheet">
</body>
</html>
LaravelでSASS(.scss)を使って実装する手順
PHPを使ったLaravelで実際に使う例を紹介します。
前提条件は以下になります。
- Larvel MixでWebpackを使ってコンパイルしているプロジェクト。
- cssの設計はFLOCSSを使用
実装手順
実装手順は以下の4ステップになります。
ファーストビューやメインのコンテンツで使うcssのみをまとめた、mainview.scssを作成する
ファーストビューやメインのコンテンツで使うcssのみをまとめた、mainview.scssは以下のようになります。
@charset 'utf-8';
// foundation
@forward "foundation/variable";
@forward "foundation/mixin";
@forward "foundation/normalize";
@forward "foundation/base";
// layout
@forward 'layout/grid/grid';
@forward "layout/header";
@forward "layout/container";
// object - component
@forward "object/component/breadcrumb";
@forward "object/component/title";
@forward "object/component/btn";
@forward "object/component/link";
@forward "object/component/pagenation";
@forward "object/component/error";
// object - project
// object - utility
@forward "object/utility/display";
@forward "object/utility/space";
@forward "object/utility/typography";
ファーストビューやメインコンテンツ以外のcssファイルをまとめたbottomview.scssを作成する
ファーストビューやメインコンテンツ以外のcssファイルをまとめたbottomview.scssを作成します。
@charset 'utf-8';
// foundation
@forward "foundation/variable";
@forward "foundation/mixin";
// layout
@forward "layout/footer";
ここでは、フッターに必要なスタイルと、その際に必要になる変数とミクシンを記述したファイルを読み込んでいます。
Laravel Mixでコンパイル対象のファイルを設定する
resources/sass/*.scss
にマッチするファイルを'public/css'
配下に.cssとしてコンパイルするように「webpack.mix.js」に設定を記述します。
const mix = require('laravel-mix');
const glob = require('glob');
glob.sync('resources/sass/*.scss').map(function(file) {
mix.sass(file, 'public/css')
.options({
processCssUrls: false,
postCss: [
require('autoprefixer')({ grid: true })
]
})
.version()
})
・autoprefixerとは何か?
必要なベンダプレフィックスを自動で付けてくれる便利なツールです。
なお、Laravel以外でLaravel Mixを使う場合はglob.sync~の上に以下を記述します。
mix.setPublicPath('./public')
これがないとコンパイル後のファイルがpublic配下に生成されません。(コンパイルが途中で止まってしまいます)
共通レイアウト用のビューを作成し、コンパイル後のCSSファイルを読み込む
共通レイアウト用のビューを作成し、コンパイル後のCSSファイルを読み込む。
ここでは、CSSファイルを読み込む以外に以下の設定も合わせて行います。
必要に応じて、canonicalを設定したり、meta情報を変更するサービスや条件分岐を入れます。(ここでは詳細は省きます)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<meta name="description" content="{{ $_meta['description'] }}">
<meta name="keywords" content="{{ $_meta['keywords'] }}">
<title>{{ $_meta['title'] }}</title>
<!-- OGP -->
<meta name="twitter:card" content="summary_large_image">
<meta property="og:site_name" content="{{ $_meta['site_name'] }}">
<meta property="og:title" content="{{ $_meta['title'] }}">
<meta property="og:description" content="{{ $_meta['og_description'] ?? '' }}">
<meta property="og:type" content="website">
<meta property="og:url" content="{{ url()->current() }}">
<meta property="og:locale" content="ja_JP">
@if (isset($_meta['og_image']))
<meta property="og:image" content="{{ $_meta['og_image'] ?? '' }}">
@endif
<meta name="csrf-token" content="{{ csrf_token() }}">
{{-- Favicon & Apple Touch Icon--}}
<link rel="icon shortcut" href="{{ asset("/img/favicon.ico") }}">
<meta name="apple-mobile-web-app-title" content="{{ $_meta['siteName'] }}">
<link rel="apple-touch-icon" href="{{ asset("/img/apple-touch-icon.png") }}">
<link rel="shortcut icon" href="{{ origin_url( asset("/img/favicon.ico") ) }}">
<link rel="manifest" href="{{ asset('/site.webmanifest') }}">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#fff">
{{-- ファーストビューとメインコンテンツのスタイルの読み込み --}}
<style type="text/css">
<?= file_get_contents(public_path('css/mainview.css')); ?>
</style>
@yield('jsonld')
</head>
<body>
@include('layouts.header')
<main id="l-body" class="@yield('contentClass')">
@yield('content')
</main>
@include('layouts.footer')
<div id="js-btn-to-top" class="c-btn-to-top"></div>
{{-- ファーストビューとメインコンテンツ以外のスタイルの読み込み --}}
<link href="{{ asset('css/bottomview.css') }}" rel="stylesheet">
@yield('cssCode')
{{-- JS --}}
<script defer src="{{ asset('js/app.js') }}"></script>
@yield('jsCodeBody')
</body>
</html>