🐱

WordPress 公式テーマの制作(ブロックテーマ編)

に公開

さて前回こんな記事を書いたわけですが、
https://zenn.dev/369code/articles/6360fe969cde71
今回は流行りのブロックテーマについて書いていこうと思います。
自分が作る際に、そこそこ検索したのですが、まじでがっつり書かれてるサイトがほぼないのですよ。
なので結構手探りでやっていった感じですね。
Create Block Themeなんていうプラグインもあるらしいですが、これは半分以上できあがってから知りましたね。使ってみたんですが、自分のしたいことには使えなかった感じ。
あ、でもtheme.jsonを簡単に記載できるって点は評価します(笑)。

テーマ名の選定(英数字)

公式に提出するレベルのテーマを作成するうえで一番肝心なのが、このテーマ名になります。
適当に好きな名前を付けて、いざ提出となったとき、テーマのアップロードで
「既に使われている名前です。アップロードできません」
って出たときの絶望感は半端ありません。
まずテーマの名前を付けるときは、とにかくググる。

WordPress公式テーマ内で名前を検索する。
公式に無くても、有料で販売してるテーマもあるんです。
同一名称は避けたいですよね。
googleで「WordPress theme XX」で名前を検索する。
これで同一名称のテーマが出なければほぼ大丈夫だと思います。
テーマ名のフォルダをwp-content/themesの中に作成しましょう。
ちなみにですが、1単語の場合はそのままフォルダ名にできますが、2単語以上で構成されてるものはハイフンでつなぐことをおすすめします。

ここから下でyour-themeの記載が多数出ますが、コードを使用の際は、決定したテーマ名(TEXT DOMAIN名)に変更してください。

ブロックテーマの基本構造

ブロックテーマは従来のクラシックテーマとは大きく異なる構造を持ちます。
index.phpはさして重要でもなく、表示に必要なファイルはtemplatesの中身が肝になります。
index.phpの代わりに使用されるのが、templates/index.htmlになります。

your-theme/
├── assets/
│   ├── css/
│   └── js/
├── style.css # テーマ情報とスタイル
├── index.php # 必須(空でも可)
├── functions.php # テーマ機能 
├── theme.json # テーマ設定(重要)
├── screenshot.png # テーマプレビュー画像(jpgでもOK, 1200X900px)
├── readme.txt # テーマ説明&著作権等
└── templates/ # HTMLテンプレート
    ├── index.html #必須
    ├── front-page.html
    ├── single.html
	├── page.html 
    ├── search.html
    ├── archive.html
	└── 404.html 
└── parts/ # テンプレートパーツ
    ├── header.html 
    ├── footer.html 
    └── sidebar.html #必要であれば
└── patterns/ # ブロックパターン
    ├── hero-section.php 
    ├── contact-section.php 
    ├── header.php
    └── footer.php
└── languages/ # 翻訳ディレクトリ (必要であれば)
    ├── ja.po
    └── ja.mo

必須ファイルindex.html

例えば従来のクラシックテーマでindex.phpのコードはこうなります。

index.php
<!DOCTYPE html>
<html>
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>">
<title><?php wp_title( '|', true, 'right' ); ?></title>
<link rel="stylesheet" href="<?php echo esc_url( get_stylesheet_uri() ); ?>" type="text/css" />
<?php wp_head(); ?>
</head>
<body>
<h1><?php bloginfo( 'name' ); ?></h1>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<h2><?php the_title(); ?></h2>

<?php the_content(); ?>
<?php wp_link_pages(); ?>
<?php edit_post_link(); ?>

<?php endwhile; ?>

<?php
if ( get_next_posts_link() ) {
next_posts_link();
}
?>
<?php
if ( get_previous_posts_link() ) {
previous_posts_link();
}
?>
<?php else: ?>
<p>No posts found. :(</p>
<?php endif; ?>
<?php wp_footer(); ?>
</body>
</html>

HTMLの構造が全て書かれているのが判ります。
ところが、ブロックテーマでは、index.phpは存在するだけで空白です。
templates/index.htmlがクラシックテーマのindex.phpと同じ働きをします。

index.html
<!-- wp:template-part {"slug":"header","tagName":"header"} /-->

<!-- wp:group {"tagName":"main","layout":{"type":"constrained"}} -->
<main class="wp-block-group">
	<!-- wp:pattern {"slug":"your-theme/main-section"} /-->
    <!-- wp:pattern {"slug":"your-theme/contact-section"} /-->
</main>
<!-- /wp:group -->

<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->

気づきましたか?HTMLの構造が見えません。
じゃあ、wp:template-part/headerを見てみます。

header.html
<!-- wp:group {"align":"full","layout":{"type":"default"}} -->
<div class="wp-block-group alignfull">
	<!-- wp:group {"layout":{"type":"constrained"}} -->
	<div class="wp-block-group">
		<!-- wp:group {"align":"wide","style":{"spacing":{"padding":{"top":"var:preset|spacing|30","bottom":"var:preset|spacing|30"}}},"layout":{"type":"flex","flexWrap":"nowrap","justifyContent":"space-between"}} -->
		<div class="wp-block-group alignwide" style="padding-top:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30)">
			<!-- wp:site-title {"level":0} /-->
			<!-- wp:group {"style":{"spacing":{"blockGap":"var:preset|spacing|10"}},"layout":{"type":"flex","flexWrap":"nowrap","justifyContent":"right"}} -->
			<div class="wp-block-group">
				<!-- wp:navigation {"overlayBackgroundColor":"base","overlayTextColor":"contrast","layout":{"type":"flex","justifyContent":"right","flexWrap":"wrap"}} /-->
			</div>
			<!-- /wp:group -->
		</div>
		<!-- /wp:group -->
	</div>
	<!-- /wp:group -->
</div>
<!-- /wp:group -->

htmlどころかbodyタグ、headerタグすらないことに気づきましたか?
無いんです。header.htmlをindex.htmlでテンプレートとして読み込むときにheaderタグの中身として自動で読み込むんです。

じゃあ、headタグとかbodyタグはというと、WordPress本体のwp-includesディレクトリにある、template-canvas.phpを基本に構成されます。

template-canvas.php
<?php
/**
 * Template canvas file to render the current 'wp_template'.
 *
 * @package WordPress
 */

/*
 * Get the template HTML.
 * This needs to run before <head> so that blocks can add scripts and styles in wp_head().
 */
$template_html = get_the_block_template_html();
?><!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
	<meta charset="<?php bloginfo( 'charset' ); ?>" />
	<?php wp_head(); ?>
</head>

<body <?php body_class(); ?>>
<?php wp_body_open(); ?>

<?php echo $template_html; ?>

<?php wp_footer(); ?>
</body>
</html>

$template_html でブロックテーマを表示してます。
つまり、直接headタグ・bodyタグに直接の記入は出来なくなってます。
必要な場合は、functions.phpの中でアクションフックを使って、wp_head()やwp_footer()に追加していく形になります。

はい、少しずつ気が遠くなっていきますね。えぇ私もそうでした。

必須ファイル style.css

クラシックテーマ同様、style.cssは大事なファイルです。
ここにテーマの全情報が詰まってると言っても過言ではありません。
必要な内容をしっかり記載しましょう。

style.css
/**
 * Theme Name:        テーマの一意の名前
 * Theme URI:         ユーザーがテーマに関する詳細情報を確認できるWebページのURL(任意)
 * Description:       テーマの説明
 * Version:           テーマのバージョン、記述方法X.X もしくは X.X.X
 * Author:            あなたの名前(WordPress.orgユーザーであればユーザー名)
 * Author URI:        テーマを作成した個人または組織のURL(任意)
 * Tags:              one-column (テーマがサポートする機能のコンマ区切りリスト)
 * Text Domain:       翻訳のテキストドメインに使用される一意の文字列
 * Domain Path:       /languages (テーマの翻訳が保存されている場所への相対パス)
 * Tested up to:      テーマがテストされた最後のWordPressバージョン
 * Requires at least: テーマが動作する最も古いWordPressバージョン
 * Requires PHP:      テーマが動作する最も古いPHPバージョン
 * License:           テーマのライセンス
 * License URI:       テーマのライセンスのURL
 */

公式テーマとして提出するためのライセンスは、公式で以下のように記載されています。

テーマはGNU一般公衆利用許諾書と互換性がある必要があります
GPL互換のライセンスであればどれでも使用できますが、WordPress と同じライセンス (「GPLv2 以降」) を使用することを強くお勧めします。

GNUを見て適切なライセンスを付与することが必要です。
私はよくGPLv3を使用させてもらってます。

テキストドメインですが、テーマ名が1単語ならそのテーマ名をそのまま。2単語以上なら基本的にテーマのフォルダ名であれば間違いないです。

タグは使用できる一覧は以下の通りになります。(一部抜粋)
各項目から選べます。

{"Layout":["grid-layout","one-column","two-columns","three-columns","four-columns","left-sidebar","right-sidebar","wide-blocks"],"Features":["accessibility-ready","block-patterns","block-styles","buddypress","custom-background","custom-colors","custom-header","custom-logo","custom-menu","editor-style","featured-image-header","featured-images","flexible-header","footer-widgets","front-page-post-form","full-site-editing","full-width-template","microformats","post-formats","rtl-language-support","sticky-post","style-variations","template-editing","theme-options","threaded-comments","translation-ready"],"Subject":["blog","e-commerce","education","entertainment","food-and-drink","holiday","news","photography","portfolio"]}

私が書いたのはこんな感じ。翻訳対応で、ブロックテーマで、エディタでフルサイト編集使えますよ的な内容です。

Tags: one-column, block-patterns, block-styles, custom-colors, custom-logo, editor-style, full-site-editing, translation-ready

要は作ったブロックテーマの説明を明確にできるタグを選ぶことです。

header.html

クラシックテーマとは異なり、ブロックテーマではpartsフォルダのheader.htmlとfooter.htmlがheader.phpとfooter.phpの代わりになります。
でも大きく異なるのは、header.htmlのタグは<header>タグから始まること。(divでも可)
本来のHTMLの構成要素ヘッダーとしてのheader.htmlになっています。

header.html
<!-- wp:group {"style":{"spacing":{"padding":{"top":"20px","bottom":"20px"},"margin":{"top":"0px","bottom":"0px"}}},"backgroundColor":"raft-bg-alt","layout":{"inherit":true}} -->
<div class="wp-block-group has-raft-bg-alt-background-color has-background"
     style="margin-top:0px;margin-bottom:0px;padding-top:20px;padding-bottom:20px">

    <!-- wp:group {"className":"alignwide","layout":{"type":"flex","flexWrap":"nowrap","justifyContent":"space-between"}} -->
    <div class="wp-block-group alignwide">

        <!-- wp:group {"layout":{"type":"flex"}} -->
        <div class="wp-block-group">
            <!-- wp:site-title {"fontSize":"large"} /-->
        </div>
        <!-- /wp:group -->

        <!-- wp:group {"layout":{"type":"flex"}} -->
        <div class="wp-block-group">
            <!-- wp:navigation {"layout":{"type":"flex","setCascadingProperties":true,"justifyContent":"right"},"style":{"spacing":{"blockGap":"32px"}}} /-->
        </div>
        <!-- /wp:group -->

    </div>
    <!-- /wp:group -->
</div>
<!-- /wp:group -->

<div>で始まっていますが、index.htmlなどのテンプレートからheaderとして読み込まれる際に<header></header>タグが自動的に付与されます。
footer.htmlの場合も同じなので割愛します。

patterns を使ったオリジナルパターン

先ほどのheader.htmlの中身ですが、まるごとpatternsに入れて使いまわしすることもできます。
その場合、header.htmlは以下のように書き換えます。

header.html
<!-- wp:pattern {"slug":"your-theme/header"} /-->

patternsにある、your-theme/headerという固有のスラッグ名のヘッダーを読み込むという意味です。
そしてpatternsの中にheader.phpを作成します。
元のheader.htmlに書いていた内容を丸ごとコピペします。

パターン化すると何が便利かというと、

  • デザインの使いまわし
  • PHPが中に書ける
    この2点が有用になります。
    PHPを使って変数を呼び出したいときはphpのほうが便利ですよね。
    header/footerに限らず、パーツやテンプレートの中身の呼び出しはパターンを使うほうが便利です。
header.php
<?php
/**
 * Title: Main header
 * Slug: your-theme/header
 * Categories: header
 */
?>

<!-- wp:group {"style":{"spacing":{"padding":{"top":"20px","bottom":"20px"},"margin":{"top":"0px","bottom":"0px"}}},"backgroundColor":"raft-bg-alt","layout":{"inherit":true}} -->
<div class="wp-block-group has-raft-bg-alt-background-color has-background"
     style="margin-top:0px;margin-bottom:0px;padding-top:20px;padding-bottom:20px">

    <!-- wp:group {"className":"alignwide","layout":{"type":"flex","flexWrap":"nowrap","justifyContent":"space-between"}} -->
    <div class="wp-block-group alignwide">

        <!-- wp:group {"layout":{"type":"flex"}} -->
        <div class="wp-block-group">
            <!-- wp:site-title {"fontSize":"large"} /-->
        </div>
        <!-- /wp:group -->

        <!-- wp:group {"layout":{"type":"flex"}} -->
        <div class="wp-block-group">
            <!-- wp:navigation {"layout":{"type":"flex","setCascadingProperties":true,"justifyContent":"right"},"style":{"spacing":{"blockGap":"32px"}}} /-->
        </div>
        <!-- /wp:group -->

    </div>
    <!-- /wp:group -->
</div>
<!-- /wp:group -->

最初の3行が大事です。

  • Title: Main header
  • Slug: your-theme/header
  • Categories: header
    タイトルはわかりやすいパターン名をつけ、スラッグにはあなたのテーマ名と固有の名前を。
    カテゴリはheaderを選びましたが、これはパターン一覧に表示される領域を示してます。
    あなたのテーマだけの表示領域をつくりたいなら、オリジナルのカテゴリの名前を入れて、functions.phpでその名前を登録する必要があります。

オリジナルプロックパターン

functions.php
// Register block patterns
function your-theme_register_block_patterns() {
    register_block_pattern_category(
        'your-theme_patterns',
        array('label' => __('Your Theme Patterns', 'your-theme'),
        'description' => __('Your Theme collection', 'your-theme'))
    );
}
add_action('init', 'your-theme_register_block_patterns');

これを登録しておくことで、オリジナルのパターンを作ったとき、カテゴリ名をyour-theme_patternsに指定してまとめて表示ができます。

パターン作ったらとにかくブロックエディタで確認

ブロックテーマのテンプレートやパターンの記入の仕方は、WordPress独自のマークアップになります。
自分でガリガリ書いてもできないことは無いですが、きちんと書かないと、ブロックエディタで編集できなくなります。
独自で作ったパターンをテーマのエディタから編集すると、ダメな場合は「予期しないエラー」や「修復しますか」等のダイアログが表示されています。うっかり修復を押すと、今までのコードが真っ白にw
ベストな方法は、ブロックエディタで1からデザインを作って、コードエディターを表示し、そのコードをコピペして、パターンのPHPファイルに貼り付ける方法。
マークアップが正確に記載されているので安心して使えます。

functions.php

テーマでの設定をここに記載することになります。
クラシックテーマではほとんどの設定はここに書きますが、ブロックテーマの場合は、theme.jsonがあるので、アクションフック系をここへ書くことになります。

ここに自分が使ってる一例を記載します。

functions.php
if (!defined('ABSPATH')) {
    exit;
}

define('YOUR_THEME_VERSION', wp_get_theme()->get('Version'));
define('YOUR_THEME_ASSETS', get_template_directory_uri() . '/assets');

function your_theme_setup() {
    add_theme_support('wp-block-styles');
    add_theme_support('block-patterns');
    add_theme_support('block-templates');
    add_theme_support('block-template-parts');
    add_theme_support('editor-styles');
    add_editor_style(get_parent_theme_file_uri('assets/css/editor-style.css'));
    add_theme_support('post-formats', array('aside', 'audio', 'chat', 'gallery', 'image', 'link', 'quote', 'status', 'video'));
}
add_action('after_setup_theme', 'your_theme_setup');

function your-theme_register_block_patterns() {
    register_block_pattern_category(
        'your-theme_patterns',
        array('label' => __('Your Theme Patterns', 'your-theme'),
        'description' => __('Your Theme collection', 'your-theme'))
    );
}
add_action('init', 'your-theme_register_block_patterns');

function your-theme_enqueue_scripts() {
    wp_enqueue_style('your-theme-style', get_stylesheet_uri(), array(), YOUR_THEME_VERSION);

    if (is_singular() && comments_open() && get_option('thread_comments')) {
        wp_enqueue_script('comment-reply');
    }
}
add_action('wp_enqueue_scripts', 'your-theme_enqueue_scripts');

クラシックテーマの時のfunctions.phpに比べ、記載内容が多少減ってます。
あとブロックテーマ固有として、以下のパラメータは自動で有効になります。

post-thumbnails
responsive-embeds
editor-styles
html5
automatic-feed-links

カスタマイザーはなく、デザインエディターになるので、custom-logoやcustom-backgroundも必要無いです。
最初はちょっと戸惑いますよね。

theme.json 必須file

ブロックテーマの肝ともいえるファイルです。(クラシックテーマでも設置できます)
テーマのグルーバルな設定からスタイルの設定まで広域に定義するファイルになってます。
公式サイトでからの引用です。

色、タイポグラフィ、間隔のコントロールなどのブロック機能をユーザー インターフェースで有効にし>ます。
カスタム カラー パレット、デュオトーン フィルター、背景グラデーションを構成します。
フォント ファミリ、Web フォントのバンドルなどのタイポグラフィ機能の定義。
独自の CSS カスタム プロパティを追加します。
コア スタイル システム内で作業して全体的なデザインを調整します。

theme.jsonの基本構造は以下になります。

theme.json
{
	"$schema": "https://schemas.wp.org/trunk/theme.json",
	"version": 3,
	"settings": {},
	"styles": {},
	"customTemplates": {},
	"templateParts": {},
	"patterns": []
}

$schemaとversionは定型文のように思ってもらえばOK。
その下から説明します。

  • settings
    ブロックコントロールの定義やプリセットの構成
  • styles
    WEBサイトやブロック・色・フォントなどのスタイルの設定
  • customTemplates
    templatesフォルダーのテンプレートのデータ
  • templateParts
    partsフォルダのテンプレートのデータ
  • patterns
    patternsフォルダに登録されたスラッグの配列

設定が非常に細かいので、手書きは判ってないときついです。
ここで、Create Block Themeプラグインを使ってスタイルを設定すると、自動でtheme.jsonを作ってくれるので、JSONがよくわからなくても大丈夫。(ホントは理解して作ってほしいけど)

公式ページで詳細な説明があるので、一度じっくり目を通しておくことをおすすめします。
Theme.jsonの設定

ライセンスや著作権など

公式に提出するテーマは、GNU General Public Licenseと互換性がある必要があります。
自分で販売する場合はその限りではありませんが、GPLに準拠してるほうが利用者に好まれます。
またテーマで使用するすべてのファイル(画像・動画・コード)もGPLまたはGPL互換ライセンスに準拠している必要があります。
つまりあなた自身のものであるかあなたの所有物である必要があります。
READMEに著作権情報を含めて各種ライセンスも全て記載します。

CDNを使ったリンクは認められないので注意しましょう。
Googleフォント等は、ダウンロードして圧縮し、assetsフォルダに入れてtheme.jsonから読み込みます。
カスタム投稿やショートコードも使用できません。
プラグイン機能を含めることもできませんし、サードパーティ製ライブラリの使用もできません。

翻訳

基本的にテーマのPHPで使用される文字列は、すべて翻訳できる必要があります。
patternsフォルダのphpが主な翻訳対象になります。
翻訳文字列を作るには以下のように書きます。
書き方はお好みでどうぞ。

__('read more', 'your-theme');
_e('read more', 'your-theme'); //echo出力処理付き
esc_html_e('read more', 'your-theme'); //echo出力処理付き

テーマのすべての翻訳文字列を、専用のソフトを使って読み込み、翻訳ファイルを作成します。
詳細は以下で記載してますので参考にしてください。
https://zenn.dev/369code/articles/32b56aa482a129

Theme check プラグインのインストール

ここまで作り上げれば、最後はTheme Check というWordPressのプラグインをインストールします。
インストールして有効化したあと、テーマメニューにtheme checkという項目が出てきますので、クリックしてチェックを実行します。
これで警告がなくなるまで修正します。
ここまで来たらほぼ提出の合格ラインです。

WordPress テーマ提出

提出してから先は、WordPress独自の基準がありますので、担当するレビューアとのやりとりになります。
初めての時はたくさん修正が求められると思いますが、めげずに頑張ってください。

Discussion