チャイルドテーマの少しややこしい話(スタイルシートの読み込み順の制御)

チャイルドテーマのややこしい話なんて、ネタのようで少し気が引けるのですが、

実際にチャイルドテーマを使ってテーマを作りこんでいく時に知っておくといいと思うので、あえて書こうかなと思います。

チャイルドテーマを作成しようと思ったら、大抵

子テーマ Codex

を読み込んで、さぁ、作りましょうという事になるんじゃないかなと思います。

子テーマは、少なくとも 1つのディレクトリ(子テーマディレクトリ)と、2つのファイル(style.css と functions.php) から構成されます。以下を作成する必要があります。

チャイルドテーマに、functions.php と style.css を追加します。

以前は @import: を使用して親テーマのスタイルシートをインポートしていましたが、これはもはや良い方法ではありませんので注意してください。

という事で、functions.phpに アクションフックで、

add_action( 'wp_enqueue_scripts', 'theme_enqueue_styles' );
function theme_enqueue_styles() {
 wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );

}

親テーマのスタイルシートを読み込む設定をしました。ここまでは、バッチリ

2017/1/24 デフォルトテーマのstyle.cssのロードについて疑問がわいたので追記、

twentyfifteen-style-cssで、チャイルドテーマのstyle.cssが読み込まれています。

「チャイルドテーマで @import(../twentyfifteen/style.css);を記述するといいよ」と、ごく初期のチャイルドテーマのために、

	// Load our main stylesheet.
	wp_enqueue_style( 'twentyfifteen-style', get_stylesheet_uri() );

として、わざわざ、チャイルドテーマを読みこむようにしている。
テーマの他のCSSは、

	// Load the Internet Explorer specific stylesheet.
	wp_enqueue_style( 'twentyfifteen-ie', get_template_directory_uri() . '/css/ie.css', array( 'twentyfifteen-style' ), '20141010' );
	wp_style_add_data( 'twentyfifteen-ie', 'conditional', 'lt IE 9' );

テンプレートディレクトリを参照している。

これは、デフォルトテーマのtwenty seventeenまで、代々このコーディングスタイルが継承されている

 @import(../twentyfifteen/style.css);を記述するといいよ というアイディアを保証するためのコードが、5代にわたるデフォルトテーマで維持されていることは疑問だと思う。

チャイルドテーマのスタイルは、@importではなく、wp_enqueue_style()を使いましょうという事が当たり前になっているのに、

wp_enqueue_style()で、チャイルドテーマのstyle.cssだけを呼び出すだけだと、親のstyle.cssが読み込まれないというのは、もはやバグと思うのは、私だけだろうか?

add_action( 'wp_enqueue_scripts', 'theme_enqueue_styles' );
function theme_enqueue_styles() {
 wp_enqueue_style( 'child-style', get_stylesheet_directory_uri() . '/style.css', array('twentyseventeen-style') );
}

を記述した場合に、デフォルトテーマが親テーマのスタイルシートを、チャイルドディレクトリからロードしようとする挙動に目をつぶって、@importルールの機能を守り続ける理由などあるのだろうか?

<link rel='stylesheet' id='twentyseventeen-style-css' href='http://www.example.com/wp/wp-content/themes/child-twentyseventeen/style.css?ver=4.7.1' type='text/css' media='all' />
<link rel='stylesheet' id='child-style-css' href='http://www.example.com/wp/wp-content/themes/child-twentyseventeen/style.css?ver=4.7.1' type='text/css' media='all' />

Child Theme stylesheet loading issue · Issue #1075 · Automattic/_s

子テーマのスタイルシートは、通常は自動的に読み込まれます。そうでない場合は、同様にエンキューする必要があります。 依存関係として「parent-style」を設定し、その後に子テーマのスタイルシートをロードしましょう。

依存関係というのは、先に読み込まれるスタイルシート(親テーマのスタイル)と後で読み込まれる(チャイルドテーマのスタイル)の順序を正しく指定しないと、
逆になっている場合は、親テーマのスタイルルールと、同じルールを書き込んでも、上書きできなくなるので、ここのところ重要です。

add_action( 'wp_enqueue_scripts', 'theme_enqueue_styles' );
function theme_enqueue_styles() {
 wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
 wp_enqueue_style( 'child-style',
 get_stylesheet_directory_uri() . '/style.css',
 array('parent-style')
 );
}

Codexのコードwp_enqueue_style()の第三引数が array(‘parent-style’) がスタイルシートの読み込みの順番を決めるので、これはやっておくべきですね。

( wp_enqueue_style()は、上から順に読み込まれるので、後から、チャイルドテーマスタイルを書き込めば、array()でもOKみたいな話は、ここでは話の外とさせてください )

さて、ではこれで、「チャイルドテーマの設定は、ぱっちりなのでしょうか?」というのが、「ややこしい話」です。

wp_enqueue_style()は、依存関係(スタイルシートの読み込み順 )の指定が、「肝」

言い方を変えると、スタイルシートが style.cssだけだったらいいけど、複数スタイルシートが使われる場合には、wp_enqueue_style()によるスタイルシートの読み込みには、「読み込み順を指定したら、必ずhtmlソースを確認したほうがいいよーん」です。

Codexのwp_enqueue_styleが array()になっていますが、それは間違いという事ではなく、例えば、Twentytenのように、スタイルを1枚しか持っていない場合多分問題は出ないですし、複数スタイルシートを持っているテーマの場合は、問題になるといったテーマに依存しているという点を理解しましょう

チャイルドテーマの作成例から、スタイルの読み込みを、実例で考えてみます。

Twentyfifteen の チャイルドテーマを作ってみます。

style.css ファイルだけが存在するチャイルドテーマ

<link rel='stylesheet' id='twentyfifteen-fonts-css' href='' type='text/css' media='all' />
<link rel='stylesheet' id='genericons-css' href='' type='text/css' media='all' />
<link rel='stylesheet' id='twentyfifteen-style-css' href='http://.../wp-content/themes/child-fifteen/style.css?ver=4.4.1' type='text/css' media='all' />

チャイルドテーマが最後に読み込まれて、読み込み順はナイスですね。

しかし、@import ルールで親テーマを読み込まなくてはいけないですね。

なぜ、@importルールを使うべきではないと言われているのか

「サイトのパフォーマンスに影響する」という事が根拠のようで、@importを使ったCSSの読み込みは、一つ終了したら、次の@importのスタイルを、読み込んでいくため、ブラウザでの処理に時間がかかる。出来るだけ並行して読み込める環境にしようという事で、link要素を使った記述にするといった考え方から、「やっぱし、link要素を使おう。」 という事で、

Codexでは

これはもはや良い方法ではありませんので注意してください。

と記述されたのだろうと思います。

link要素を書き出す設定を行ったチャイルドテーマ

functions.phpにlink要素を書き出すコードを記述してみましょう

Codexの例に倣って、functions.phpに以下のコードを追加してみます。

function add_child_style() {
	wp_enqueue_style( 'twentyfifteen-style', get_template_directory_uri(). '/style.css', array( ) );	
	wp_enqueue_style( 'customtheme-style', get_stylesheet_directory_uri(). '/style.css', array( 'twentyfifteen-style' ) );	
}
add_action( 'wp_enqueue_scripts', 'add_child_style' );
<link rel='stylesheet' id='twentyfifteen-style-css' href='...twentyfifteen/style.css?ver=4.4.1' type='text/css' media='all' />
<link rel='stylesheet' id='customtheme-style-css' href='...child-fifteen/style.css?ver=4.4.1' type='text/css' media='all' />
<link rel='stylesheet' id='twentyfifteen-fonts-css' href='https://fonts.googleapis.com/css....' type='text/css' media='all' />
<link rel='stylesheet' id='genericons-css' href='...genericons/genericons.css?ver=3.2' type='text/css' media='all' />

どうでしょう?

フォントスタイルや、アイコンフォントのスタイルが、チャイルドテーマのCSSの後から読み込まれていますね。

そうです、「 CSS 命 」の人は、もうわかりましたね!

詳細度を上げて、こうやればできるとか、アーやればできるという人もいるかもしれませんが、ざっくり言えば 「アウト―!!!」ですね。

正しい、スタイルシートの読み込み順のチャイルドテーマ

<link rel='stylesheet' id='twentyfifteen-fonts-css' href='https://fonts.googleapis.com/css...' type='text/css' media='all' />
<link rel='stylesheet' id='genericons-css' href='...genericons/genericons.css?ver=3.2' type='text/css' media='all' />
<link rel='stylesheet' id='twentyfifteen-style-css' href='...twentyfifteen/style.css?ver=4.4.1' type='text/css' media='all' />
<link rel='stylesheet' id='customtheme-style-css' href='...child-fifteen/style.css?ver=4.4.1' type='text/css' media='all' />

Twentyfifteenのチャイルドテーマのスタイルシートの読み込み順を正しく設定する

function add_child_style() {
	wp_enqueue_style( 'twentyfifteen-style', get_template_directory_uri(). '/style.css', array( 'twentyfifteen-fonts','genericons' ) );	
	wp_enqueue_style( 'customtheme-style', get_stylesheet_directory_uri(). '/style.css', array( 'twentyfifteen-style' ) );	
	
}
add_action( 'wp_enqueue_scripts', 'add_child_style' );

のように、読み込み順をきっちり指定しておくのが肝である事がわかりました。

多くの場合、CSSの読み込み順が異なっていても、実装段階では、大きくレイアウトが崩れることはないでしょう。

しかし、それは トラブルの予備軍である事あきらかです。

アイコンの色を変えようとしたんですけど、「色が変更できませーん」みたいなことになるかもしれません。

詳細度を上げて、都度対処しても、どんどん管理しにくいスタイルを量産する事にもなっていくかもしれません。

htmlソースを確認しましょう。正しく読み込まれている事を確認する事を確認するだけで、より管理しやすいWEBサイトになるはずです。

Tips

‘twentyfifteen-fonts’,’genericons’ とかいう、親テーマのスタイルのハンドル名をどうやって調べたらいいの ?

htmlソースを確認しましょう。link要素の id=”twentyfifteen-fonts-css” を確認して、-css というサフィックスを取り除いたのが、ハンドル名になります。

余談

なんで、「コードを正しく記述しましょう」じゃなくて、「htmlソースを確認しましょう」と書いているかについて、

チャイルドテーマのスタイルの設定だけなら、コードの記述だけの話でいいのですが、wp_enqueur_style()って関数は、テーマだけが使うものではなく、コアのプログラムも、プラグインも、使っているわけで、それらがコラボして、一つのWEBサイトを表示しているわけです。
なので、ほんとのことを言えば、これらすべてのスタイルの登録が正しく行われているという事と、それらをコントロールするためにも、wp_enqueue_style()の使い方というのは大事で そのためには、やっぱり「ソースを見るのが一番」と思ったからでした。

プラグインのスタイル変更したいってこともよくありますよね 

wp_enqueue_style()をうまく使って、すべてのスタイルの制空権をチャイルドテーマで奪取しよう。

余談 2 更にややこしく

子テーマのスタイルシートは、通常は自動的に読み込まれます。そうでない場合は、同様にエンキューする必要があります。

これは、Codexの引用ですが、通常自動的に、読み込まれる でも、そうでない場合というのは、どういう場合なのか、考えてみましょう。

上の一連の説明でいうと、twentyfifteen-style というスタイルのハンドル名を使っていますが、

親テーマが使っているハンドル名を使わないで、独自の 例えば、my-parent等という新しいハンドル名で、wp_enqueue_style()を使うと、

チャイルドテーマのstyle.cssは、twentyfifteen-style-id として自動的に読み込まれます。

つまり、twentyfifteen-style という親テーマで定義してあるハンドル名を使って、wp_enqueue_style()すると、チャイルドテーマの読み込みに使うはずだったものが、親テーマのスタイルで使用されてしまうので、結果として、チャイルドテーマのstyle.cssは、自動的に書き出されなくなる。

こういった挙動は、wp_enqueue_script()なんかと、感覚的に異なりますが、「通常は自動的に読み込まれます。そうでない場合は…」という挙動の違いが何を根拠に行われているかの、答えではないかと思います

余談 3 チャイルドテーマのstyle.cssに親テーマのstyle.cssをコピーして使いたいんですけどといった場合の考慮点

親テーマのスタイル、子テーマのスタイル別々に記述しないほうが、構成がシンプルになる等の理由で、コピーして使いたいという話を聞くことがあります

コピーすれば、@importを使う必要もなくfunctions.phpに、PHPを記述する必要もありません。

そのような場合に、考慮しておいたほうがいいんじゃないかと思う点

  • 親テーマのスタイルシートがアップデートした時に、変更が反映されなくなるといった点
  • 親テーマで、テーマの画像ファイルなどから、アイコンなどの画像が指定されている場合に、単にコピーしただけでは、画像が表示されなくなる点

画像が表示されなくなる理由

親テーマのスタイルで、画像などを指定する場合 相対参照が使われます。

.arrow{background:(images/arrow.jpg);}

コピーしただけだと、チャイルドテーマのimagesを参照する事になり、そのままでは画像などが表示されなくなります。

2017/5/31 追記

チャイルドテーマを使っているのに、親テーマのスタイルシートが反映しないことがある。

なぜなのか?

チャイルドテーマのstyle.cssのコメントのバージョン番号によるいたずら

チャイルドテーマstyle.cssに以下のようなコメントがあるとします。

/*
Theme Name: my theme
Theme URI: http://example.com/
Description: チャイルドテーマの不条理
Author: Tenman
Author URI: http://www.example.com/author/
Version: 1.403
License: GNU General Public License v2.0
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: raindrops
Template: raindrops

/

で、親テーマが更新されたので、アップデートします。

適切にバージョン番号が処理されている場合チャイルドテーマのバージョン番号が使われます。

<link rel='stylesheet' id='style-css' href='http://www.example.com/wp/wp-content/themes/raindrops/style.css?ver=1.403' type='text/css' media='all' />

このバージョンクエリーは、キャッシュ除けに使われるわけですが、親テーマを更新する時に、いちいちチャイルドテーマのバージョン番号を変えないので、キャッシュが残り親テーマの更新が反映しないという事が起きます。

一方、テンプレートの更新は、イレギュラーな事がない限り反映するので、運が悪いと「レイアウトがおかしくなった」なんてことも想像がつきます。

WordPress4.7から使えるようになった。直接ファイルの更新日をクエリーに加えてやるような方法をとれば、このような事は起きないのかもしれません。

WordPress 4.7 get_theme_file_uri() get_theme_file_path() – WordPress Snippet

[emulsion_relate_posts]