2026年7月29日

2026年7月29日

WordPressの子テーマを正しく作成する方法【アップデート対策】

はじめに

WordPressのテーマを直接編集してカスタマイズしてしまうと、テーマのアップデートで変更がすべて上書きされてしまいます。子テーマを正しく作成することで、親テーマのアップデートに影響されることなく、安全にカスタマイズを維持できます。

症状・原因

  • 親テーマのCSSや functions.php を直接編集したため、アップデートで変更が消えてしまった
  • 子テーマを作ったが @import で親CSSを読み込んでおり、パフォーマンスが悪い
  • 子テーマの functions.php と親テーマの functions.php の読み込み順序がわからない
  • get_stylesheet_directory()get_template_directory() の違いが理解できていない

解決手順

ステップ1:子テーマディレクトリと style.css を作成する

wp-content/themes/ 内に子テーマ用のディレクトリを作成し、style.css にテーマ情報を記述します。

/*
 * 子テーマの style.css
 * ファイルパス: wp-content/themes/mytheme-child/style.css
 *
 * Theme Name:   My Theme Child
 * Theme URI:    https://example.com/
 * Description:  Twenty Twenty-Four の子テーマ
 * Author:       あなたの名前
 * Author URI:   https://example.com/
 * Template:     twentytwentyfour
 * Version:      1.0.0
 * License:      GNU General Public License v2 or later
 * License URI:  http://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:  mytheme-child
 */

/*
 * 子テーマのカスタムスタイルはここに追記します。
 * 親テーマのスタイルは functions.php で wp_enqueue_style() を使って読み込みます。
 * ここに @import を書いてはいけません(パフォーマンスが悪化します)。
 */

/* カスタムスタイルの例 */
:root {
    --color-primary: #0073aa;
    --color-secondary: #00a32a;
}

.site-header {
    background-color: var(--color-primary);
}

.entry-title a:hover {
    color: var(--color-secondary);
    text-decoration: underline;
}

Template ヘッダーには親テーマのディレクトリ名(style.cssTheme Name ではなく)を正確に記述してください。

ステップ2:functions.php で親テーマのCSSを正しく読み込む

子テーマの functions.phpwp_enqueue_style() を使って親テーマのスタイルシートを読み込みます。@import は使用しないでください。

<?php
// wp-content/themes/mytheme-child/functions.php

/**
 * 親テーマと子テーマのスタイルシートを正しく読み込む
 *
 * 重要:@import ではなく wp_enqueue_style() を使うこと
 */
function mytheme_child_enqueue_styles() {
    // 親テーマのスタイルシートを取得
    $parent_style = 'parent-style';
    $parent_version = wp_get_theme(get_template())->get('Version');

    // 親テーマのスタイルを登録・読み込み
    wp_enqueue_style(
        $parent_style,
        get_template_directory_uri() . '/style.css',
        [],           // 依存関係なし
        $parent_version
    );

    // 子テーマのスタイルを読み込み(親テーマに依存)
    wp_enqueue_style(
        'child-style',
        get_stylesheet_directory_uri() . '/style.css',
        [$parent_style],  // 親テーマのスタイルを依存として指定
        wp_get_theme()->get('Version')
    );
}
add_action('wp_enqueue_scripts', 'mytheme_child_enqueue_styles');

// ブロックエディター(Gutenberg)用のスタイルも読み込む場合
function mytheme_child_enqueue_block_editor_styles() {
    wp_enqueue_style(
        'child-editor-style',
        get_stylesheet_directory_uri() . '/editor-style.css',
        [],
        wp_get_theme()->get('Version')
    );
}
add_action('enqueue_block_editor_assets', 'mytheme_child_enqueue_block_editor_styles');

ステップ3:親テーマのテンプレートファイルをオーバーライドする

親テーマのテンプレートを変更したい場合は、同じファイル名で子テーマにコピーして編集します。

// 子テーマでテンプレートファイルをオーバーライドする仕組み

// WordPress のテンプレート読み込み優先順位:
// 1. 子テーマ (get_stylesheet_directory())
// 2. 親テーマ (get_template_directory())

// 例:wp-content/themes/mytheme-child/single.php
// この single.php が親テーマの single.php より優先される

// カスタムテンプレートファイルの例
// wp-content/themes/mytheme-child/single-news.php

<?php get_header(); ?>

<main id="main" class="site-main">
    <?php while ( have_posts() ) : the_post(); ?>
        <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
            <header class="entry-header">
                <?php the_title('<h1 class="entry-title">', '</h1>'); ?>
                <div class="entry-meta">
                    <time datetime="<?php echo get_the_date('c'); ?>">
                        <?php echo get_the_date(); ?>
                    </time>
                </div>
            </header>

            <?php if ( has_post_thumbnail() ) : ?>
                <div class="post-thumbnail">
                    <?php the_post_thumbnail('large'); ?>
                </div>
            <?php endif; ?>

            <div class="entry-content">
                <?php the_content(); ?>
            </div>
        </article>
    <?php endwhile; ?>
</main>

<?php get_footer(); ?>

テンプレート部品(パーツ)のオーバーライド例:

  • header.php → 子テーマに header.php を作成
  • footer.php → 子テーマに footer.php を作成
  • template-parts/content.php → 子テーマに同じパスで作成

ステップ4:子テーマの functions.php を活用する

子テーマの functions.php は親テーマの functions.php より先に読み込まれます。この特性を活かして、親テーマの関数を拡張・置き換えできます。

<?php
// wp-content/themes/mytheme-child/functions.php

// 親テーマの関数をフックで変更する例

// 親テーマで登録されたスクリプトのバージョンを変更
function mytheme_child_modify_scripts() {
    // 親テーマが登録したスクリプトを解除
    wp_dequeue_script('parent-main-script');

    // 修正版を読み込む
    wp_enqueue_script(
        'child-main-script',
        get_stylesheet_directory_uri() . '/js/main.js',
        ['jquery'],
        '1.0.0',
        true  // フッターで読み込み
    );
}
add_action('wp_enqueue_scripts', 'mytheme_child_modify_scripts', 20); // 優先度20(親より後)

// 親テーマで pluggable な関数をオーバーライド
// 親テーマで function_exists() チェックがある関数のみ上書き可能
if ( ! function_exists('parent_theme_function') ) {
    function parent_theme_function() {
        // 子テーマでの再実装
        return '子テーマのカスタム処理';
    }
}

// フィルターで親テーマの出力を変更
function mytheme_child_excerpt_length( $length ) {
    return 80; // 親テーマが設定しているものを上書き
}
add_filter('excerpt_length', 'mytheme_child_excerpt_length', 999);

// 子テーマ独自のカスタムポストタイプを追加
function mytheme_child_register_post_types() {
    // 子テーマ固有の投稿タイプ
    register_post_type('portfolio', [
        'label'         => 'ポートフォリオ',
        'public'        => true,
        'has_archive'   => true,
        'show_in_rest'  => true,
        'supports'      => ['title', 'editor', 'thumbnail'],
    ]);
}
add_action('init', 'mytheme_child_register_post_types');

ステップ5:get_stylesheet_directory と get_template_directory の違いを理解する

子テーマ開発で最も混乱しやすい2つの関数の使い分けを解説します。

<?php
// get_stylesheet_directory() と get_template_directory() の違い

// get_stylesheet_directory() / get_stylesheet_directory_uri()
// → 現在有効なテーマ(子テーマ)のディレクトリを返す
// → 子テーマが有効な場合: wp-content/themes/mytheme-child/
// → 親テーマが直接有効な場合: wp-content/themes/twentytwentyfour/

$child_dir = get_stylesheet_directory();
// 例: /var/www/html/wp-content/themes/mytheme-child

$child_uri = get_stylesheet_directory_uri();
// 例: https://example.com/wp-content/themes/mytheme-child

// get_template_directory() / get_template_directory_uri()
// → 親テーマ(テンプレートテーマ)のディレクトリを返す
// → 子テーマが有効な場合: wp-content/themes/twentytwentyfour/(親テーマ)
// → 親テーマが直接有効な場合: wp-content/themes/twentytwentyfour/(同じ)

$parent_dir = get_template_directory();
// 例: /var/www/html/wp-content/themes/twentytwentyfour

$parent_uri = get_template_directory_uri();
// 例: https://example.com/wp-content/themes/twentytwentyfour

// 実践的な使い方

// 子テーマのファイルを読み込む(子テーマのファイルを探す)
require_once get_stylesheet_directory() . '/inc/custom-functions.php';

// 親テーマのファイルを読み込む(親テーマのファイルを探す)
require_once get_template_directory() . '/inc/template-tags.php';

// 画像やJSのURLを生成する
$child_image_url = get_stylesheet_directory_uri() . '/images/logo.png';
$parent_icon_url = get_template_directory_uri() . '/assets/icons/icon.svg';

// テンプレートファイルを子テーマ → 親テーマの順で探す
// locate_template() は自動的にこの順序で探してくれる
$template = locate_template(['template-parts/hero.php']);
if ( $template ) {
    load_template($template);
}

注意事項

  • 子テーマの style.cssTemplate ヘッダーには、親テーマのディレクトリ名(フォルダ名)を正確に記述してください。Theme Name と異なる場合があります。
  • 子テーマの functions.php で始まる必要がありますが、閉じタグ ?> は不要(むしろ記述しない方が安全)です。
  • ブロックテーマ(FSE対応テーマ)の子テーマでは、style.css の設定方法が一部異なります。親テーマが theme.json を使用している場合、子テーマでも theme.json で設定を上書きできます。

まとめ

子テーマの作成は、style.css への Template ヘッダーの記述と、functions.php での wp_enqueue_style() による親テーマCSSの読み込みが基本です。get_stylesheet_directory()get_template_directory() を正しく使い分けることで、子テーマから親テーマのリソースを安全に参照できます。関連記事:WordPressテーマカスタマイザーに独自設定を追加する方法

お気軽にご相談ください