WordPress でテーマをカスタマイズする


この記事は「初めての WordPress」の続きです。前回で元のブログからの引っ越しはほぼ終了しました。これからは WordPress のカスタマイズをやっていきます。

カスタマイズと言えばテーマです。Wordpress は無料で良質のテーマがたくさん手に入る1ので、特別なことをしなければカスタマイズの必要はありません。

 

しかしそのテーマはほとんどが英語圏用のものです。日本語のブログで使うときには微調整がしたいこともあります。

今回はそういう、オリジナルのテーマを一から作るまでもない、小粒な変更を行ってみました。

元になるテーマを決める

まずは改造する元のテーマを決めます。今回使うことにしたのは Something Fishy です。

WordPress › Something Fishy « Free WordPress Themes
http://wordpress.org/extend/themes/something-fishy

このテーマを WordPress の管理画面からインストールすると、次のディレクトリにテーマの内容物が入ります。

wordpress/wp-content/themes/something-fishy/

このテーマのファイルを直接修正してはいけません。なぜかというと、テーマがバージョンアップしたときに、修正が全て消えてしまうからです。

子テーマを作る

そこで子テーマ(Child Themes)という仕組みを使います。これは、親となるテーマのファイルをそのまま使いながら、修正したい分だけを自分で上書きするのです。

これならば、テーマがバージョンアップしたときには親テーマの構成ファイルだけが書き換わり、修正した部分が消えることがありません。

子テーマを作るには、まず親テーマと同じディレクトリに子テーマのディレクトリを作ります。

wordpress/wp-content/themes/something-fishy-custom/

今回は語尾に -custom を付けましたが、これは各人の自由です2

style.css を用意する

子テーマに絶対必要なファイルは style.css です。このファイルを作成することにより、Wordpress はこれを一つのテーマとして認識します。

style.css の中身はこんな感じです。

/*
Theme Name: something-fishy-custom
Template: something-fishy
*/

簡単ですね。正式には著作権表示やバージョン番号も必要なのでしょうが、今回は個人的に使うテーマなのでこれで十分です。

この時点で WordPress の管理画面を見ると、今回作成した子テーマが選択可能になっていることがわかります。

テーマの設定

テーマの設定

しかし、この時点ではこの子テーマはうまく動きません。CSS が空っぽも同然だからです。

親テーマの CSS を読み込む

子テーマでは親テーマの修正部分だけを記述するものですから、

  1. 親テーマの CSS
  2. 子テーマの CSS

の順に、CSS を読み込むようにすべきです。

古典的には、これに CSS の @import 識別子が使われてきました3

/*
Theme Name: something-fishy-custom
Template: something-fishy
*/

@import url('../something-fishy/style.css');

/* この後にカスタム CSS を書く */

しかし、パフォーマンス的な観点から見ると、これは余り良い方法ではありません。

IE では従来から @import によりページの読み込みが遅くなる問題が知られており、@import の使用を避け、2 つ以上の <link> で代用することが推奨されています4

[css] @importを使うべきでない理由 | Screw-Axis
http://screw-axis.com/2009/06/07/css-importを使うべきでない理由/

IE 氏ね というのは僕にも同感なのですが、だからといって無視するわけにはいきません。ここは順当に、2 つ(以上)の CSS を順に読み込むことで解決しましょう。

wp_register_style()wp_enqueue_style()

WordPress では CSS を読み込むための専用の関数が用意されています。それを使うのが最近の流行っぽいです。

手順としては以下のようになります。

  1. wp_register_style() で CSS を登録する。
  2. wp_enqueue_style() で CSS をキュー(順番待ち)に加える。

wp_enqueue_style() で登録とキューへの追加を一気にやる方法もありますが、今回は標準通りに行きます。

wp_register_style() の使い方

Function Reference/wp register style « WordPress Codex
http://codex.wordpress.org/Function_Reference/wp_register_style

wp_register_style($handle, $src, $deps, $ver, $media);
$handle CSS ファイルの識別名。
$src CSS ファイルの URL。
$deps 依存する CSS。配列で指定する。
$ver CSS のバージョン番号。
$media media 属性。
wp_register_style(
  'parent-stylesheet', // 親テーマのスタイシート
  '/wp-content/themes/something-fishy/style.css',
  false,
  '1.0'),
  'all',
);

wp_register_style(
  'child-stylesheet', // 子テーマのスタイシート
  '/wp-content/themes/something-fishy-custom/style.css',
  array('parent-stylesheet'), // 親テーマのスタイルシートに依存する
  filemtime('/path/to/css/child-style.css'), // ファイルの更新日時をバージョン番号とする
  'all',
);

親テーマの CSS と子テーマの CSS を読み込みその依存関係を設定しています。これにより、親テーマの CSS が子テーマの CSS より前に読み込まれることが保証されるのです。

また、wp_register_style() では登録する CSS の順番は問われません。実際に HTML が描画されるときは CSS の依存関係に従って <link> タグが生成されるのです。

wp_enqueue_style() の使い方

CSS を wp_register_style() で登録したら、次は wp_enqueue_style() で描画順番待ちの列に並ばせます。

wp_enqueue_style($handle);
wp_enqueue_style($handle, $src, $deps, $ver, $media);

書式は 2 種類あります。wp_register_style() と組み合わせて使うならばその 1 の方が簡便で良いです。

// wp_register_style() で登録した後に書く
wp_enqueue_style('parent-stylesheet');
wp_enqueue_style('child-stylesheet');

ここでは便宜上、parentchild の前に書いていますが、実際には順番は関係ありません。上述の通り、順番は依存関係によって自動的に変わります。逆に言えば、依存関係をきちんと設定しないと希望の順番では読み込まれません。

コードはどこに書くの?

さて、そもそもこれらの PHP コードはどこに書けば良いでしょうか? WordPress のテーマでは style.css と同様、必ず読み込まれる PHP ファイルがあります。それが functions.php です。

まずは、素直に上のコードを並べてみます。

// 親テーマの CSS を登録する
wp_register_style(
  'parent-stylesheet', // 親テーマのスタイシート
  '/wp-content/themes/something-fishy/style.css',
  false,
  '1.0'),
  'all',
);


// 子テーマの CSS を登録する
wp_register_style(
  'child-stylesheet', // 子テーマのスタイシート
  '/wp-content/themes/something-fishy-custom/style.css',
  array('parent-stylesheet'), // 親テーマのスタイルシートに依存する
  filemtime('/path/to/css/child-style.css'), // ファイルの更新日時をバージョン番号とする
  'all',
);

// 親テーマの CSS を順番待ちに追加する
wp_enqueue_style('parent-stylesheet');
// 子テーマの CSS を順番待ちに追加する
wp_enqueue_style('child-stylesheet');

多分これでも一応うまく動くはずですが、CSS が二重に読み込まれるなどの不具合が出ると思います。なぜでしょう?

それは、子テーマの functions.php が、親テーマの functions.php より前に読み込まれるからです。

親テーマの CSS はどこで読み込まれているのか

今回利用した Something Fishy テーマでは以下の部分で CSS の登録(と順番待ちへの追加)が行われています。

/**
 * Enqueue scripts and styles
 */
function somethingfishy_scripts() {
    global $post;

    wp_enqueue_style( 'underthesea-style', get_stylesheet_uri() );

    wp_enqueue_script( 'underthesea-small-menu', get_template_directory_uri() . '/js/fishy.js', array( 'jquery' ), '20120206', true );

    wp_enqueue_script( 'underthesea-parallax', get_template_directory_uri() . '/js/parallax.js', array( 'jquery' ) );

    wp_enqueue_style( 'underthesea-portlligatsans' );
    wp_enqueue_style( 'underthesea-oswald' );
    wp_enqueue_style( 'underthesea-pacifico' );

    if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
        wp_enqueue_script( 'comment-reply' );
    }

    if ( is_singular() && wp_attachment_is_image( $post->ID ) ) {
        wp_enqueue_script( 'somethingfishy_keyboard-image-navigation', get_template_directory_uri() . '/js/keyboard-image-navigation.js', array( 'jquery' ), '20120202' );
    }
}
add_action( 'wp_enqueue_scripts', 'somethingfishy_scripts' );

色を付けた部分が重要です。まずは最初の wp_enqueue_style()

    wp_enqueue_style( 'underthesea-style', get_stylesheet_uri() );

get_stylesheet_uri() はテーマのスタイルシートファイル style.css の URL を返す関数です。便利ですが、意味を理解して使わないと事故の元になります。なぜかというと、この関数はテーマの名称に応じて違った URL を返すからです。

今回使用した親テーマ Something Fishy をそのまま利用する場合、上記 wp_enqueue_style() によって以下のような <link> タグが生成されます。

<link rel='stylesheet' id='underthesea-style-css' href='/wp-content/themes/something-fishy/style.css?ver=3.5' type='text/css' media='all' />

themes/something-fishy が URL に含まれているのでこれは親テーマの CSS だとわかります。

これを、子テーマ something-fishy-custom で利用したらどうなるでしょう?

<link rel='stylesheet' id='underthesea-style-css' href='/wp-content/themes/something-fishy-custom/style.css?ver=3.5' type='text/css' media='all' />

themes/something-fishy-custom でわかるとおり、子テーマの CSS が読み込まれています。get_stylesheet_uri() という同じ関数、かつ、underthesea-style という同じ識別名で別の CSS が読み込みまれています。

親テーマで読み込まれた CSS を登録解除する

希望通り、親テーマの CSS → 子テーマの CSS という順番で CSS を読み込ませるためには、次の関数を使って一度親テーマの CSS を登録解除する必要があります。

Function Reference/wp deregister style « WordPress Codex
http://codex.wordpress.org/Function_Reference/wp_deregister_style

wp_deregister_style($handle);

今回の場合は、以下のように指定します。

// 親テーマの functions.php で読み込まれた CSS を登録解除する
wp_deregister_style('underthesea-style');
// 親テーマの CSS を順番待ちに追加する
wp_enqueue_style('parent-stylesheet');
// 子テーマの CSS を順番待ちに追加する
wp_enqueue_style('child-stylesheet');

add_action() で順番待ちに入れるのを遅らせる

上に挙げた親テーマ Something Fishyfunctions.php の一部には、最下行に以下のような関数が記載されています。

add_action( 'wp_enqueue_scripts', 'somethingfishy_scripts' );

これはいわゆるアクションフックです。ここで登録したコールバック関数(この場合は somethingfishy_scripts)が、後でアクション(wp_enqueue_scripts)を起動するときに実行されます。

ここは親テーマの流儀に従って、子テーマの CSS をアクションフックによって順番待ちに追加することにします。

// CSS を順番待ちに追加する関数
function somethingfishy_custom_styles() {
  // 親テーマの functions.php で読み込まれた CSS を登録解除する
  wp_deregister_style('underthesea-style');
  // 親テーマの CSS を順番待ちに追加する
  wp_enqueue_style('parent-stylesheet');
  // 子テーマの CSS を順番待ちに追加する
  wp_enqueue_style('child-stylesheet');
}

// コールバックを登録する
add_action('wp_print_styles', 'somethingfishy_custom_styles');

アクションの名称が違いますね? 親テーマのスクリプトでは wp_enqueue_scripts だったのに、子テーマでは wp_print_styles になっています。

これは、wp_print_styles の方が、wp_enqueue_scripts より後に実行されるアクションだからです。

プラグイン API/アクションフック一覧 – WordPress Codex 日本語版
http://wpdocs.sourceforge.jp/プラグイン_API/アクションフック一覧

20. get_header
21. wp_head
22. wp_enqueue_scripts
23. wp_print_styles
24. wp_print_scripts
25. get_template_part_loop
26. loop_start*

ちょっと場当たり的ですがしょうがありません。

子テーマの functions.php が親テーマの functions.php の前に読み込まれるという規則がある以上、子テーマで CSS を読み込む関数は wp_euqueue_scripts より後に実行されるアクション wp_print_scripts に、アクションフックとして登録する必要があります。

functions.php 完成版

以上をまとめると、子テーマ something-fishy-customfunctions.php を以下のように書けます。

// 親テーマの CSS を登録する
wp_register_style(
  'parent-stylesheet', // 親テーマのスタイシート
  '/wp-content/themes/something-fishy/style.css',
  false,
  '1.0'),
  'all',
);

// 子テーマの CSS を登録する
wp_register_style(
  'child-stylesheet', // 子テーマのスタイシート
  '/wp-content/themes/something-fishy-custom/style.css',
  array('parent-stylesheet'), // 親テーマのスタイルシートに依存する
  filemtime('/path/to/css/child-style.css'), // ファイルの更新日時をバージョン番号とする
  'all',
);

// CSS を順番待ちに追加する
function somethingfishy_custom_styles() {
  // 親テーマの functions.php で読み込まれた CSS を登録解除する
  wp_deregister_style('underthesea-style');
  // 親テーマの CSS を順番待ちに追加する
  wp_enqueue_style('parent-stylesheet');
  // 子テーマの CSS を順番待ちに追加する
  wp_enqueue_style('child-stylesheet');
}

// コールバックを登録する
add_action('wp_print_styles', 'somethingfishy_custom_styles');

これでやっと完成です。

まとめ

スタイルシート一つ登録するだけでもなかなか大変でした。ポイントを箇条書きにしてみます。

  • 子テーマを作成するときに必要なファイルは以下の 2 つ。
    • style.css
    • functions.php
  • CSS を <link> タグを使って出力するときは次の 2 つの関数を functions.php に記述する。
    • wp_register_style() → CSS を登録する。
    • wp_euqueue_scripts() → CSS を順番待ちに追加する
  • 既に登録された CSS を登録解除するときは wp_deregister_style() を使う。
  • 順番待ちに追加された CSS はアクションフックの形で登録された関数で描画する。

今回は Something Fishy というテーマを例にしましたが、細部(CSS の識別名やフックすべきアクション名など)はテーマによって異なると思います。この辺は柔軟に対応するしかないですね。


  1. これが Movable Type から乗り換えた理由の一つ。 
  2. 余計なトラブルを防ぐために、使用する文字は半角英数字+単純な記号で納めておくのが吉。 
  3. 偉そうなこと言ってますが、僕自身 WordPress 暦は一ヶ月ほどしかありません。 ですから昔のことなんてよく知らんのです。 
  4. もちろん、一つの <link> で済むように CSS を minify するのが最善なのは言うまでもありません。 

コメントを残す