自作テーマファイルで運用する

WordPressの始め方

ブロックテーマとtemplate-canvas.php

更新日:

template-canvas.phpは、WordPressデフォルトテーマのTwenty Twenty-Twoから採用されたブロックテーマで使用されているテーマファイルです。

ブロックテーマでは、基本的にすべてのページは wp-includes/template-canvas.php をテンプレートとして表示されます。

【参考】

WordPress バージョン6.1で、ブロックテーマTwenty Twenty-Twoバージョンが1.2から1.3へ更新されました。

また、WordPress バージョン6.1からブロックテーマTwenty Twenty-Threeバージョン: 1.0が追加されました。

ブロックテーマ

公式サイトは、ブロックテーマを以下の様に説明しています。

ブロックテーマは、ブロックを使用して構築された WordPress テーマの一種です。

ブロック テーマのすべての部分をサイトエディターで編集できます。

WordPress はバージョン 5.9 からブロック テーマをサポートします。

デフォルトテーマのTwenty Twenty、Twenty Twenty-Oneはクラシックテーマですが、Twenty Twenty-Twoはブロックテーマとなっています。

引用 WordPress公式サイトブロックテーマ

サイトエディター

この機能はブロックテーマを使用している場合に利用できます。

ブロック テーマのエディタは、サイトの全体のレイアウトをグローバル レベルで設定できる機能を持つFSE(Full Site Editing)エディタです。

サイトエディターを使用した変更のほとんどはサイト全体に適用されます。

そのため、ブロック テーマはFSEテーマとも呼ばれます。

サイトエディタCodexマニュアル

クラシックテーマ使用時のエディタ
ブロックテーマ使用時のサイトエディタ

エディタの切り替え

Twenty Twenty-Twoテーマの左上にあるWordPressのアイコンをクリックすることで、エディタの切り替えができます。

サイト:トップページのテンプレートが表示され編集ができます。

テンプレート:サイトテンプレートの一覧が表示され編集ができます。

サイトテンプレートの編集では(単一投稿 (区切りなし) 固定ページ 個別投稿 検索 空白 ページ (区切りなし) ホーム 404 ページ (大きなヘッダー) アーカイブ インデックス )の作成・編集ができます。

テンプレートパーツ:カスタマイズ可能なテンプレートパーツの一覧が表示されます

ブロックテーマの要素

ブロック テーマは、ルートフォルダにstyle.css ファイルとtemplatesフォルダにindex.htmlを必要とします。

WordPress 5.9以前との互換のためルートフォルダにindex.php (ブロックテーマでは未使用)も必要とします。

また、すべての HTML テンプレート ファイルはtemplatesフォルダに配置する必要があります。

footer.htmlやheader.htmlなどのテンプレートパーツはオプションです。

スタイルやブロックの設定情報を持つtheme.json構成ファイルはオプションです。

テンプレートパーツは、 partsフォルダに配置される必要があります。

オプションですが利用が推奨されています。

ブロックテーマを拡張するため必須ファイル以外に以下のファイルを使用することができます。

theme.json
functions.php
PHP files
CSS
images
JavaScript

【参考】Codex記述箇所

ブロックテーマではPHPファイルの代わりに HTML ファイルを使用します。

テンプレート階層はクラシックテーマとブロックテーマで同じです。

ブロックテーマファイル構成例

【ブロックテーマファイル構成例】
patterns ディレクトリ
      - example.php
parts ディレクトリ
      - footer.html
      - header.html
templates ディレクトリ
      - 404.html
      - archive.html
      - index.html (必須)
      - singular.html
functions.php
index.php
README.txt
screenshot.png
style.css (必須)
theme.json
Twenty Twenty-Two ブロックテーマファイル構成
Twenty Twenty-Twoでstyle.css (必須)が存在しない場合

以下のエラーが表示されテーマが認識されません。

壊れているテーマ
以下のテーマはインストール済みですが、足りない部分があります。
名前  twentytwentytwo
説明 Stylesheet is missing.

Twenty Twenty-Twoでindex.html (必須)が存在しない場合

エラーは表示されずテーマとして認識されますが、ブロックテーマの機能が使えません。

ブロックエディタメニューが未表示

ブロックテーマのメリット

ブロック テーマはスケーラビリティとパフォーマンスを向上させるために構築されています。

ブロック テーマはスケーラビリティとパフォーマンスを向上させるために構築されています。

  •  ブロック テーマはブロック用スタイルのみを読み込むだけでページをレンダリングするため、読み込みパフォーマンスが向上します
  • ブロック テーマはwp_enqueue_style()【※1】を必要としません。
  • Theme.json はadd_theme_support()の下記すべてを処理できます。
    ■アイキャッチ画像 ■head タグ内のフィードのリンク ■投稿フォーマット ■HTML5 ■カスタムヘッダー ■カスタムヘッダー ■カスタムロゴ ■タイトルタグ
  • コンテンツへのスキップ、キーボード ナビゲーション、ランドマークなどのアクセシビリティ機能は、追加のコードを追加することなく自動的に生成されます
  • ブロックテーマを使用すると、ユーザーはコードなしで Web サイトのすべての部分を編集できます
  • スタイル インターフェイスを使用することで、ユーザーは Web サイトとブロックの色とタイポグラフィ(フォントなど)をカスタマイズできます。

/wp-include/template-canvas.phpに関して

Twenty Twenty-TwoやTwenty Twenty-Threeブロックテーマを使用した場合のWordPress起動時の流れは、調査中です。

①index.phpwp-blog-header.php

template-loader.php内のdo_action( ‘template_redirect’ );

の順でテンプレートのコードが取得されます。

template-canvas.phpget_the_block_template_html()関数【※2】でレンダリングされた後にecho $template_html;でHTML出力されます。

<?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; // phpcs:ignore WordPress.Security.EscapeOutput ?>

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

【メモ】wp-includes/block-template.php => locate_block_template()

/**
 * Find a block template with equal or higher specificity than a given PHP template file.
 *
 * Internally, this communicates the block content that needs to be used by the template canvas through a global variable.
 *
 * @since 5.8.0
 *
 * @global string $_wp_current_template_content
 *
 * @param string   $template  Path to the template. See locate_template().
 * @param string   $type      Sanitized filename without extension.
 * @param string[] $templates A list of template candidates, in descending order of priority.
 * @return string The path to the Full Site Editing template canvas file, or the fallback PHP template.
 */
function locate_block_template( $template, $type, array $templates ) {
	global $_wp_current_template_content;

	if ( ! current_theme_supports( 'block-templates' ) ) {
		return $template;
	}

	if ( $template ) {
		/*
		 * locate_template() has found a PHP template at the path specified by $template.
		 * That means that we have a fallback candidate if we cannot find a block template
		 * with higher specificity.
		 *
		 * Thus, before looking for matching block themes, we shorten our list of candidate
		 * templates accordingly.
		 */

		// Locate the index of $template (without the theme directory path) in $templates.
		$relative_template_path = str_replace(
			array( get_stylesheet_directory() . '/', get_template_directory() . '/' ),
			'',
			$template
		);
		$index                  = array_search( $relative_template_path, $templates, true );

		// If the template hierarchy algorithm has successfully located a PHP template file,
		// we will only consider block templates with higher or equal specificity.
		$templates = array_slice( $templates, 0, $index + 1 );
	}

	$block_template = resolve_block_template( $type, $templates, $template );

	if ( $block_template ) {
		if ( empty( $block_template->content ) && is_user_logged_in() ) {
			$_wp_current_template_content =
			sprintf(
				/* translators: %s: Template title */
				__( 'Empty template: %s' ),
				$block_template->title
			);
		} elseif ( ! empty( $block_template->content ) ) {
			$_wp_current_template_content = $block_template->content;
		}
		if ( isset( $_GET['_wp-find-template'] ) ) {
			wp_send_json_success( $block_template );
		}
	} else {
		if ( $template ) {
			return $template;
		}

		if ( 'index' === $type ) {
			if ( isset( $_GET['_wp-find-template'] ) ) {
				wp_send_json_error( array( 'message' => __( 'No matching template found.' ) ) );
			}
		} else {
			return ''; // So that the template loader keeps looking for templates.
		}
	}

	// Add hooks for template canvas.
	// Add viewport meta tag.
	add_action( 'wp_head', '_block_template_viewport_meta_tag', 0 );

	// Render title tag with content, regardless of whether theme has title-tag support.
	remove_action( 'wp_head', '_wp_render_title_tag', 1 );    // Remove conditional title tag rendering...
	add_action( 'wp_head', '_block_template_render_title_tag', 1 ); // ...and make it unconditional.

	// This file will be included instead of the theme's template file.
	return ABSPATH . WPINC . '/template-canvas.php';
}

Theme.json

テーマのスタイルとブロック設定情報を持つブロックテーマの構成ファイルです。

テンプレート エディタを利用するにはtheme.json をテーマに追加必要があります。

Twenty Twenty-Twoバージョン: 1.2のtheme.json

Twenty Twenty-Twoバージョン: 1.2の実際のtheme.jsonは下記のとおりです。

theme.jsonのバージョン 2仕様の詳細は、Codexオンラインリファレンスのこちらのページで参照できます。

{
	"version": 2,
	"customTemplates": [
		{
			"name": "blank",
			"title": "Blank",
			"postTypes": [
				"page",
				"post"
			]
		},
		{
			"name": "page-large-header",
			"title": "Page (Large Header)",
			"postTypes": [
				"page"
			]
		},
		{
			"name": "single-no-separators",
			"title": "Single Post (No Separators)",
			"postTypes": [
				"post"
			]
		},
		{
			"name": "page-no-separators",
			"title": "Page (No Separators)",
			"postTypes": [
				"page"
			]
		}
	],
	"settings": {
		"appearanceTools": true,
		"color": {
			"duotone": [
				{
					"colors": [ "#000000", "#ffffff" ],
					"slug": "foreground-and-background",
					"name": "Foreground and background"
				},
				{
					"colors": [ "#000000", "#ffe2c7" ],
					"slug": "foreground-and-secondary",
					"name": "Foreground and secondary"
				},
				{
					"colors": [ "#000000", "#f6f6f6" ],
					"slug": "foreground-and-tertiary",
					"name": "Foreground and tertiary"
				},
				{
					"colors": [ "#1a4548", "#ffffff" ],
					"slug": "primary-and-background",
					"name": "Primary and background"
				},
				{
					"colors": [ "#1a4548", "#ffe2c7" ],
					"slug": "primary-and-secondary",
					"name": "Primary and secondary"
				},
				{
					"colors": [ "#1a4548", "#f6f6f6" ],
					"slug": "primary-and-tertiary",
					"name": "Primary and tertiary"
				}
			],
			"gradients": [
				{
					"slug": "vertical-secondary-to-tertiary",
					"gradient": "linear-gradient(to bottom,var(--wp--preset--color--secondary) 0%,var(--wp--preset--color--tertiary) 100%)",
					"name": "Vertical secondary to tertiary"
				},
				{
					"slug": "vertical-secondary-to-background",
					"gradient": "linear-gradient(to bottom,var(--wp--preset--color--secondary) 0%,var(--wp--preset--color--background) 100%)",
					"name": "Vertical secondary to background"
				},
				{
					"slug": "vertical-tertiary-to-background",
					"gradient": "linear-gradient(to bottom,var(--wp--preset--color--tertiary) 0%,var(--wp--preset--color--background) 100%)",
					"name": "Vertical tertiary to background"
				},
				{
					"slug": "diagonal-primary-to-foreground",
					"gradient": "linear-gradient(to bottom right,var(--wp--preset--color--primary) 0%,var(--wp--preset--color--foreground) 100%)",
					"name": "Diagonal primary to foreground"
				},
				{
					"slug": "diagonal-secondary-to-background",
					"gradient": "linear-gradient(to bottom right,var(--wp--preset--color--secondary) 50%,var(--wp--preset--color--background) 50%)",
					"name": "Diagonal secondary to background"
				},
				{
					"slug": "diagonal-background-to-secondary",
					"gradient": "linear-gradient(to bottom right,var(--wp--preset--color--background) 50%,var(--wp--preset--color--secondary) 50%)",
					"name": "Diagonal background to secondary"
				},
				{
					"slug": "diagonal-tertiary-to-background",
					"gradient": "linear-gradient(to bottom right,var(--wp--preset--color--tertiary) 50%,var(--wp--preset--color--background) 50%)",
					"name": "Diagonal tertiary to background"
				},
				{
					"slug": "diagonal-background-to-tertiary",
					"gradient": "linear-gradient(to bottom right,var(--wp--preset--color--background) 50%,var(--wp--preset--color--tertiary) 50%)",
					"name": "Diagonal background to tertiary"
				}
			],
			"palette": [
				{
					"slug": "foreground",
					"color": "#000000",
					"name": "Foreground"
				},
				{
					"slug": "background",
					"color": "#ffffff",
					"name": "Background"
				},
				{
					"slug": "primary",
					"color": "#1a4548",
					"name": "Primary"
				},
				{
					"slug": "secondary",
					"color": "#ffe2c7",
					"name": "Secondary"
				},
				{
					"slug": "tertiary",
					"color": "#F6F6F6",
					"name": "Tertiary"
				}
			]
		},
		"custom": {
			"spacing": {
				"small": "max(1.25rem, 5vw)",
				"medium": "clamp(2rem, 8vw, calc(4 * var(--wp--style--block-gap)))",
				"large": "clamp(4rem, 10vw, 8rem)",
				"outer": "var(--wp--custom--spacing--small, 1.25rem)"
			},
			"typography": {
				"font-size": {
					"huge": "clamp(2.25rem, 4vw, 2.75rem)",
					"gigantic": "clamp(2.75rem, 6vw, 3.25rem)",
					"colossal": "clamp(3.25rem, 8vw, 6.25rem)"
				},
				"line-height": {
					"tiny": 1.15,
					"small": 1.2,
					"medium": 1.4,
					"normal": 1.6
				}
			}
		},
		"spacing": {
			"units": [
				"%",
				"px",
				"em",
				"rem",
				"vh",
				"vw"
			]
		},
		"typography": {
			"dropCap": false,
			"fontFamilies": [
				{
					"fontFamily": "-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,Oxygen-Sans,Ubuntu,Cantarell,\"Helvetica Neue\",sans-serif",
					"name": "System Font",
					"slug": "system-font"
				},
				{
					"fontFamily": "\"Source Serif Pro\", serif",
					"name": "Source Serif Pro",
					"slug": "source-serif-pro",
					"fontFace": [
						{
							"fontFamily": "Source Serif Pro",
							"fontWeight": "200 900",
							"fontStyle": "normal",
							"fontStretch": "normal",
							"src": [ "file:./assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2" ]
						},
						{
							"fontFamily": "Source Serif Pro",
							"fontWeight": "200 900",
							"fontStyle": "italic",
							"fontStretch": "normal",
							"src": [ "file:./assets/fonts/source-serif-pro/SourceSerif4Variable-Italic.ttf.woff2" ]
						}
					]
				}
			],
			"fontSizes": [
				{
					"size": "1rem",
					"slug": "small"
				},
				{
					"size": "1.125rem",
					"slug": "medium"
				},
				{
					"size": "1.75rem",
					"slug": "large"
				},
				{
					"size": "clamp(1.75rem, 3vw, 2.25rem)",
					"slug": "x-large"
				}
			]
		},
		"layout": {
			"contentSize": "650px",
			"wideSize": "1000px"
		}
	},
	"styles": {
		"blocks": {
			"core/button": {
				"border": {
					"radius": "0"
				},
				"color": {
					"background": "var(--wp--preset--color--primary)",
					"text": "var(--wp--preset--color--background)"
				},
				"typography": {
					"fontSize": "var(--wp--preset--font-size--medium)"
				}
			},
			"core/post-title": {
				"typography": {
					"fontFamily": "var(--wp--preset--font-family--source-serif-pro)",
					"fontWeight": "300",
					"lineHeight": "var(--wp--custom--typography--line-height--tiny)",
					"fontSize": "var(--wp--custom--typography--font-size--gigantic)"
				}
			},
			"core/post-comments": {
				"spacing": {
					"padding": {
						"top": "var(--wp--custom--spacing--small)"
					}
				}
			},
			"core/pullquote": {
				"border": {
					"width": "1px 0"
				}
			},
			"core/query-title": {
				"typography": {
					"fontFamily": "var(--wp--preset--font-family--source-serif-pro)",
					"fontWeight": "300",
					"lineHeight": "var(--wp--custom--typography--line-height--small)",
					"fontSize": "var(--wp--custom--typography--font-size--gigantic)"
				}
			},
			"core/quote": {
				"border": {
					"width": "1px"
				}
			},
			"core/site-title": {
				"typography": {
					"fontFamily": "var(--wp--preset--font-family--system-font)",
					"lineHeight": "var(--wp--custom--typography--line-height--normal)",
					"fontSize": "var(--wp--preset--font-size--medium)",
					"fontStyle": "italic",
					"fontWeight": "normal"
				}
			}
		},
		"color": {
			"background": "var(--wp--preset--color--background)",
			"text": "var(--wp--preset--color--foreground)"
		},
		"elements": {
			"h1": {
				"typography": {
					"fontFamily": "var(--wp--preset--font-family--source-serif-pro)",
					"fontWeight": "300",
					"lineHeight": "var(--wp--custom--typography--line-height--tiny)",
					"fontSize": "var(--wp--custom--typography--font-size--colossal)"
				}
			},
			"h2": {
				"typography": {
					"fontFamily": "var(--wp--preset--font-family--source-serif-pro)",
					"fontWeight": "300",
					"lineHeight": "var(--wp--custom--typography--line-height--small)",
					"fontSize": "var(--wp--custom--typography--font-size--gigantic)"
				}
			},
			"h3": {
				"typography": {
					"fontFamily": "var(--wp--preset--font-family--source-serif-pro)",
					"fontWeight": "300",
					"lineHeight": "var(--wp--custom--typography--line-height--tiny)",
					"fontSize": "var(--wp--custom--typography--font-size--huge)"
				}
			},
			"h4": {
				"typography": {
					"fontFamily": "var(--wp--preset--font-family--source-serif-pro)",
					"fontWeight": "300",
					"lineHeight": "var(--wp--custom--typography--line-height--tiny)",
					"fontSize": "var(--wp--preset--font-size--x-large)"
				}
			},
			"h5": {
				"typography": {
					"fontFamily": "var(--wp--preset--font-family--system-font)",
					"fontWeight": "700",
					"textTransform": "uppercase",
					"lineHeight": "var(--wp--custom--typography--line-height--normal)",
					"fontSize": "var(--wp--preset--font-size--medium)"
				}
			},
			"h6": {
				"typography": {
					"fontFamily": "var(--wp--preset--font-family--system-font)",
					"fontWeight": "400",
					"textTransform": "uppercase",
					"lineHeight": "var(--wp--custom--typography--line-height--normal)",
					"fontSize": "var(--wp--preset--font-size--medium)"
				}
			},
			"link": {
				"color": {
					"text": "var(--wp--preset--color--foreground)"
				}
			}
		},
		"spacing": {
			"blockGap": "1.5rem"
		},
		"typography": {
			"fontFamily": "var(--wp--preset--font-family--system-font)",
			"lineHeight": "var(--wp--custom--typography--line-height--normal)",
			"fontSize": "var(--wp--preset--font-size--medium)"
		}
	},
	"templateParts": [
		{
			"name": "header",
			"title": "Header",
			"area": "header"
		},
		{
			"name": "header-large-dark",
			"title": "Header (Dark, large)",
			"area": "header"
		},
		{
			"name": "header-small-dark",
			"title": "Header (Dark, small)",
			"area": "header"
		},
		{
			"name": "footer",
			"title": "Footer",
			"area": "footer"
		}
	]
}

CodexオンラインマニュアルのTheme.jsonのページで詳細を確認できます。

ブロックエディタでのShow Current Templateプラグインの利用

Show Current Templateプラグインはブロック テーマでは機能しません。

そのためテンプレートファイル名にはすべてtemplate-canvas.phpが表示されます。

プラグイン開発者は、今後「このプラグインはブロック テーマでは動作しません」という警告メッセージを表示するように修正するようです。

ブロック テーマではtemplate-loader.phpで決定されたテンプレートは、

template-canvas.php内の get_the_block_template_html()関数でマークアップされ$template_html変数に格納された後、echo $template_html文で出力されます。

※1
テーマのスタイルシート(style.css)リンクを出力する関数。
functions.phpにアクションフックを追加して使用する。

// functions.phpにaction-hook追加
function test_enqueue_styles() {
  wp_enqueue_style( 'main-style', get_stylesheet_uri() );
}
add_action( 'wp_enqueue_scripts', 'test_enqueue_styles' );

<--! headに出力されるリンク !>
<link rel='stylesheet' id='main-style-css'  href='http://localhost/minimalist/wp-content/themes/minimalist/style.css?ver=4.8.2' type='text/css' media='all' />

※2】get_the_block_template_html()

現在のテンプレートのマークアップを文字列として返します。

wp-includes/block-template.php内で定義されています。

function get_the_block_template_html() {
	global $_wp_current_template_content;
	global $wp_embed;

	if ( ! $_wp_current_template_content ) {
		if ( is_user_logged_in() ) {
			return '<h1>' . esc_html__( 'No matching template found' ) . '</h1>';
		}
		return;
	}

	$content = $wp_embed->run_shortcode( $_wp_current_template_content );
	$content = $wp_embed->autoembed( $content );
	$content = do_blocks( $content );
	$content = wptexturize( $content );
	$content = convert_smilies( $content );
	$content = shortcode_unautop( $content );
	$content = wp_filter_content_tags( $content );
	$content = do_shortcode( $content );
	$content = str_replace( ']]>', ']]>', $content );

	// Wrap block template in .wp-site-blocks to allow for specific descendant styles
	// (e.g. `.wp-site-blocks > *`).
	return '<div class="wp-site-blocks">' . $content . '</div>';
}

WordPressバージョン6.1

2022 年3 回目のメジャー リリースとなるWordPress バージョン6.1が2022年11月1日にリリースされました。

これに伴い、ブロックテーマTwenty Twenty-Twoもバージョン1.2から1.3へバージョンアップするとともに、新たなブロックテーマTwenty Twenty-Threeバージョン: 1.0がリリースされました。

  • B!