外部CSSファイルの中身を<style>タグの中にコピーしてレンダリングブロックを回避しよう


CSS画像
こんにちは。みなさんは、サイト制作時にCSSをどのように読み込ませてるでしょうか?
style.cssなどを<head>内に<link>などで読み込ませる方法はよく使いますよね。

私もよくこの方法でCSSを読み込んでますが 「ブラウザは外部にあるファイルを読み込む場合、そのファイルの読み込み完了まで次に進まない(レンダリングブロック)」 とゆうことを知って以来、できる限り</head>の直前にCSSを書くようにしています。

レンダリングブロックを回避できれば、表示速度の高速化に繋がります。

index.html
■ BEFORE: 外部CSSの読み込み
<head>
<link rel="stylesheet" href="../common.css">
</head>
 ↓
■ AFTER: <head> > <style>内に直接CSSを書く
<head>
<style>
 〜ここにCSSを書く〜
</style>
</head>

しかし、<style>内にCSSを書くと管理・更新などがしづらいデメリットがあります。
なので下記のようなジレンマが生まれます。

CSSファイルは外部ファイルにした方が管理・更新しやすいから外部ファイルにしておきたい。
だけど、レンダリングブロックは回避したい。

外部CSSファイルの中身を <style>内に出力する

ここでやっと本題です。
CSSファイルは外部ファイルのまま、中身だけ<style>内に出力する方法をご紹介します。
こうすることで、「レンダリングブロックの回避」と「管理・更新のしやすさ」を両立することができます。

全てのシーンで使えるわけではないですが、役に立つ時もあると思います。
今回は世界 No.1 シェアのCMS 「 WordPress 」 での方法をご紹介します。

HTMLとCSSだけではできません。

style.cssの中身を取得する

PHPの file_get_contents を使ってstyle.cssの中身を変数に格納します。
記述するファイルはテーマ内のfunctions.phpなどで問題ないと思います。
(ここでは使いまわしやすいように関数として定義)

functions.php
function my_css_minifier(){

 global $post;

 $css  = '<style>';
 $css .= file_get_contents(get_template_directory_uri().'/css/style.css');
 $css .= '</style>';

 // パスの関係が変わるので、相対パスを絶対パスに変更しておく。
 $css = str_replace('../', get_template_directory_uri().'/', $css);
 return $css
}

あとは、</head>直前にechoすればstyle.cssの中身が出力されます。

header.php
<head>
<?php echo my_css_minifier(); ?>
<?php wp_head(); ?>
</head>

wp_head()より前に出力してください。

PHPなので、サイトが表示される時に毎回「style.cssの中身を取得 → </head>直前に出力」を実行します。そのため、style.cssが更新されれば自動的に<style>内も更新されます。

これで、「レンダリングブロックの回避」と「管理・更新のしやすさ」を両立できました。

  • 外部CSSファイルを読み込みに行ってないのでレンダリングブロックが発生しない。
  • 外部CSSファイルを更新すればいいので管理・更新もしやすい。

CSSをMinifyしてさらに表示速度を向上させる

先ほどまでの作業で、この記事のタイトルでもある 「外部CSSファイルの中身を<style>タグの中にコピーしてレンダリングブロックを回避」 は、一応できました。

ここでは、もう一歩踏み込んで 「Minify(軽量化)」 したいと思います。
先ほどfunctions.phpに記載したコードを下記のように変更します。

functions.php
function my_css_minifier(){

 global $post;

 $css  = '<style>';
 $css .= file_get_contents(get_template_directory_uri().'/css/style.css');
 $css .= '</style>';
 
 // Minifier
 $css = preg_replace('/\/\*.*?\*\//s', '', $css);
 $css = str_replace(array(PHP_EOL, "  "), '', $css);

 // パスの関係が変わるので、相対パスを絶対パスに変更しておく。
 $css = str_replace('../', get_template_directory_uri().'/', $css);

 return $css
}

出力する時は先ほどと同じです。
これで改行などが削除されたCSSが出力されます。

header.php
<head>
<?php echo my_css_minifier(); ?>
<?php wp_head(); ?>
</head>

条件分岐でページ毎に対象のCSSを変更する

もし、TOPページ用のCSSや記事ページ用のCSSなど、ページによって読み込ませたいCSSが異なる場合は、if文などで条件分岐処理を追加すればOKです。

functions.php
function my_css_minifier(){

 global $post;

 $css  = '<style>';
 // 共通のCSS
 $css .= file_get_contents(get_template_directory_uri().'/css/style.css');
 if(is_front_page()){
  // Topページ用のCSS
  $css .= file_get_contents(get_template_directory_uri().'/css/top.css');
 }elseif(is_single()){
  // 記事ページ用のCSS
  $css .= file_get_contents(get_template_directory_uri().'/css/article.css');
 }

 $css .= '</style>';
 
 // Minifier
 $css = preg_replace('/\/\*.*?\*\//s', '', $css);
 $css = str_replace(array(PHP_EOL, "  "), '', $css);

 // パスの関係が変わるので、相対パスを絶対パスに変更しておく。
 $css = str_replace('../', get_template_directory_uri().'/', $css);

 return $css
}

以上。ちょっとした小ネタ(中ネタ?)の紹介でした。
需要はありそうなのであまり情報がなかったので記事にしてみました。

ご指摘・ご質問などありましたらコメントにてお知らせください。