結論
WordPress テーマ自作(クラシックテーマ)は、次の2ファイルがあれば WordPress にテーマとして認識され、有効化できます。
style.css(テーマのルートに置き、先頭のコメントにTheme Nameなどのヘッダーを書く)index.php(すべての表示の最後の受け皿になるテンプレート)
Theme Handbook は、style.css を「すべてのテーマに必要」、index.php(ブロックテーマでは templates/index.html)を「すべてのテーマで必須」と説明しています。そこから header.php・footer.php・functions.php を足し、必要に応じて single.php や page.php を追加していくのが、自作テーマの基本の順番です。
原因・仕組み
style.css のヘッダー
WordPress はテーマフォルダ直下の style.css の先頭コメントを読み、テーマ名やバージョンを取得します。サブフォルダに置くと認識されません。Handbook では Theme Name、Author、Description、Version、Requires at least、Tested up to、Requires PHP、License、License URI、Text Domain に必須の印が付いていますが、これは主に公式ディレクトリで配布する場合の要件です。自社サイト用でも、Theme Name・Version・Text Domain は最初から書いておくと後で困りません。
テンプレート階層
WordPress は表示するページの種類に応じて、テーマ内のファイルを決まった順に探します。たとえば個別投稿は single-{post-type}-{slug}.php → single-{post-type}.php → single.php → singular.php、カテゴリーは category-{slug}.php → category-{id}.php → category.php → archive.php の順です。どれも無ければ最後に index.php が使われます(Handbook の Template Hierarchy)。つまり、最初は index.php 1枚で全ページを表示させ、見た目を分けたいページだけテンプレートを足せばよい、という作り方ができます。
手順(サンプルコード)
テーマフォルダ wp-content/themes/wl1-mini/ を作り、次のファイルを置きます。
1. style.css
/*
Theme Name: WL1 Mini
Version: 1.0.0
Requires at least: 6.0
Requires PHP: 7.4
Text Domain: wl1-mini
*/
body { margin: 0; }
2. header.php(wp_head() と wp_body_open() を必ず呼ぶ)
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<?php wp_body_open(); ?>
<header class="site-header">
<a href="<?php echo esc_url( home_url( '/' ) ); ?>"><?php bloginfo( 'name' ); ?></a>
</header>
<main class="site-main">
3. footer.php(wp_footer() を必ず呼ぶ)
</main>
<footer class="site-footer">
<p>© <?php echo esc_html( wp_date( 'Y' ) ); ?> <?php bloginfo( 'name' ); ?></p>
</footer>
<?php wp_footer(); ?>
</body>
</html>
4. index.php(メインループ)
<?php get_header(); ?>
<?php if ( have_posts() ) : ?>
<?php while ( have_posts() ) : the_post(); ?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<?php the_excerpt(); ?>
</article>
<?php endwhile; ?>
<?php the_posts_pagination(); ?>
<?php else : ?>
<p><?php esc_html_e( '記事が見つかりませんでした。', 'wl1-mini' ); ?></p>
<?php endif; ?>
<?php get_footer(); ?>
5. functions.php(機能の宣言と CSS の読み込み)
<?php
add_action( 'after_setup_theme', function () {
add_theme_support( 'title-tag' );
add_theme_support( 'post-thumbnails' );
} );
add_action( 'wp_enqueue_scripts', function () {
wp_enqueue_style(
'wl1-mini-style',
get_stylesheet_uri(),
array(),
wp_get_theme()->get( 'Version' )
);
} );
<title> タグは header.php に直接書かず、title-tag のサポートを宣言して WordPress に出力させます。CSS は <link> を直書きせず wp_enqueue_style() で読み込みます(wp_enqueue_style() の使い方|説明・引数・注意点)。
動作確認(検証環境と結果)
WordPress 7.1.2(ja)、PHP 8.2.12 の CLI 検証環境で、上のファイルを wp-content/themes/wl1-mini/ に置いて確認しました。
- 4ファイルとも
php -lで構文エラーなし。 style.cssだけの状態ではwp_get_theme()->errors()が「テンプレートが不足しています。独立したテーマには templates/index.html または index.php テンプレートファイルが必要です」を返した。index.phpを追加するとエラーは消えた。Theme Nameを書かない style.css では、エラーにはならずget( 'Name' )が空、display( 'Name' )はフォルダ名(wl1-noname)になった。管理画面でテーマを見分けにくくなるので、必ず書くべきです。switch_theme( 'wl1-mini' )で有効化し、次のリクエストで index.php を出力したところ、<title>が出力され、wl1-mini-style-cssの<link>にstyle.css?ver=1.0.0が付き、投稿2件の<h2>が表示された。single.phpが無い状態でget_single_template()は空文字を返した(この場合、個別投稿も index.php で表示されます)。- 確認後は Twenty Twenty-Five に戻し、テーマフォルダを削除した。
ログは testswordpress-theme-from-scratch-minimum-files.md にあります。
WordPress テーマ自作の手順の注意点
wp_head()とwp_footer()を消すと、プラグインやコアが出力する CSS・JS・管理バーが出なくなります。wp_head() の使い方|説明・引数・注意点、wp_footer() の使い方|説明・引数・注意点 を参照してください。- テーマ内で出力する値は、
esc_html()・esc_url()などでエスケープします。bloginfo()は内部でエスケープ済みの値を出力します。 - ブロックテーマ(
templates/index.htmlとtheme.jsonで作る形式)は、本記事のクラシックテーマとは作り方が異なります。サイトエディターで編集させたいならブロックテーマを選びます。 - 既存テーマを少し変えたいだけなら、自作より子テーマが向いています(子テーマの作り方と functions.php|親テーマCSSの正しい読み込み)。
WordPress テーマ自作の手順でよくあるミス
style.cssをサブフォルダ(css/style.cssなど)にだけ置き、テーマ一覧に出てこない。index.phpを作らずfront-page.phpやsingle.phpだけ用意して、「テンプレートが不足」と表示される。<title>を手書きし、title-tagと二重に出力する。- テキストドメインを
style.cssと翻訳関数で別の文字列にしてしまう。
WordPress テーマ自作の手順のチェックリスト
- [ ] テーマ直下に
style.cssがあり、Theme Name・Version・Text Domainを書いた - [ ]
index.phpがある - [ ] header.php に
wp_head()とwp_body_open()、footer.php にwp_footer()がある - [ ] CSS・JS は
wp_enqueue_scriptsフックで読み込んでいる - [ ] 出力はエスケープしている
WordPress テーマ自作の手順のFAQ(よくある質問)
Q. 最初にどのテンプレートを足せばよいですか?
A. 一覧と個別で見た目が違うことが多いので、single.php(個別投稿)と page.php(固定ページ)から足すと効果が大きいです。共通部分は get_template_part() の使い方|説明・引数・注意点 で部品化します。
Q. スクリーンショットは必要ですか?
A. 必須ではありませんが、テーマ直下に screenshot.png を置くと管理画面のテーマ一覧に表示されます。
Q. functions.php は必須ですか?
A. 必須ファイルではありません。ただし title-tag の宣言や CSS の読み込みのために、実際にはほぼ必ず作ります(WordPress の functions.php とは|書き方の基本と、プラグインに書くべきものの見分け方)。
筆者の見解(WordPress テーマ自作の手順)
テーマ自作でつまずく原因の多くは、最初から多くのテンプレートを並べてしまい、どのファイルが表示に使われているのか分からなくなることだと考えます。index.php 1枚で全ページが出ることを確認してから、テンプレート階層に沿って1枚ずつ足す進め方の方が、結果的に早く仕上がると私は思います。また、wp_head()・wp_footer()・title-tag の3点は見た目に関係なく最初に入れておくのが、後からプラグインを入れたときの不具合を防ぐ近道だと考えています。
WordPress テーマ自作の手順の関連項目
- add_theme_support() の使い方|説明・引数・注意点
- get_template_part() の使い方|説明・引数・注意点
- wp_head() の使い方|説明・引数・注意点
- wp_footer() の使い方|説明・引数・注意点
- wp_enqueue_style() の使い方|説明・引数・注意点
- 子テーマの作り方と functions.php|親テーマCSSの正しい読み込み
- クラシックテーマのブロックエディタ対応|add_theme_support と editor-styles(準備中)
- WordPress の functions.php とは|書き方の基本と、プラグインに書くべきものの見分け方
