WordPress のカスタムブロックを作るとき、ブロックの名前やアイコン、持たせるデータ、読み込む JavaScript や CSS といった情報をまとめて書いておくのが block.json です。ひな形自体は create-block コマンドで用意できますが、そこから先「どの項目が何を意味するのか」が分からないと手を入れられません。この記事では block.json の主なプロパティを一つずつ整理し、attributes や supports の書き方、render による動的ブロックまで、実際の設定例とあわせて解説します。WordPress 6 系、apiVersion 3 を前提としています。
目次
block.json はブロックのメタデータをまとめた設定ファイル
block.json は、1つのブロックに関する情報を1か所にまとめた設定ファイルです。ブロック名やインサーターに表示されるタイトル、ブロックが保持するデータの定義、エディター用スクリプトやスタイルの場所などを、JSON という共通の形式で宣言します。JavaScript 側と PHP 側の両方から同じファイルが参照されるため、「JS では登録したのに PHP 側では認識されていない」といった食い違いが起きにくくなります。
PHP 側でやることはとてもシンプルで、block.json が置かれているディレクトリを register_block_type() に渡すだけです。
function webool_register_blocks() {
// block.json のあるディレクトリを渡すだけでよい
register_block_type( __DIR__ . '/build' );
}
add_action( 'init', 'webool_register_blocks' );
ファイル名まで指定して register_block_type( __DIR__ . '/build/block.json' ) と書くこともできますが、通常はディレクトリを渡せば中の block.json が読み込まれます。このとき、editorScript や style に書いたファイルも WordPress が自動でスクリプト・スタイルとして登録し、必要な場面(エディターだけ、フロントだけ、など)で読み込んでくれます。wp_enqueue_script() を自分で呼ぶ必要がないのは block.json の大きな利点です。
block.json の主なプロパティ
まずは全体像として、よく使うプロパティとその役割を整理します。必須なのは name と title の2つだけで、ほかは必要に応じて追加していく形になります。
| プロパティ | 説明 |
|---|---|
$schema | JSON スキーマの URL(https://schemas.wp.org/trunk/block.json)。動作には影響しないが、対応エディターで入力補完と書式チェックが効くようになる |
apiVersion | ブロックが使う Block API のバージョン。最新は 3 で、iframe 化されたエディターに対応する。省略すると 1 として扱われる |
name | 必須。ブロックを識別する一意の名前。名前空間/ブロック名 の形式が必須で、使えるのは英小文字・数字・ハイフンのみ(例: webool/notice-box) |
title | 必須。インサーターなどに表示されるブロックの表示名 |
category | インサーターでの分類。コアのカテゴリーは text / media / design / widgets / theme / embed |
icon | インサーターに表示するアイコン。block.json では Dashicons のスラッグを文字列で指定する(例: "megaphone") |
description | ブロックの短い説明。設定サイドバーやインサーターのプレビューに表示される |
keywords | 検索用の別名を配列で指定する。日本語の呼び名を入れておくと見つけやすい。最大3件 |
textdomain | 翻訳に使うテキストドメイン。title や description の翻訳に利用される |
attributes | ブロックが保持するデータの定義。型・保存先・初期値を指定する |
supports | 配置・色・余白といったエディター標準機能の有効/無効 |
example | インサーターでプレビュー表示するときに使うサンプルの属性値 |
editorScript | エディターだけで読み込む JavaScript。ブロックを登録するファイルを指定する |
script | エディターとフロントの両方で読み込む JavaScript |
viewScript | フロント側でブロックが表示されるときだけ読み込む JavaScript |
editorStyle | エディターだけで読み込む CSS |
style | エディターとフロントの両方で読み込む CSS |
render | フロント表示に使う PHP ファイル。指定すると動的ブロック(サーバー側レンダリング)になる |
スクリプトとスタイルの各項目は、"editorScript": "file:./index.js" のように file: を付けて block.json からの相対パスで書きます。すでに wp_register_script() などで登録済みのハンドル名を書くこともできますが、自前のブロックでは file: 形式が基本です。ビルドツールを使っている場合、JS ファイルと同じ場所に生成される index.asset.php から依存スクリプトとバージョンが自動的に読み取られます。
attributes でブロックが持つデータを定義する
attributes は、そのブロックがどんなデータを持つかの宣言です。見出しのテキスト、真偽値の設定、選択したサイズなど、ユーザーが編集する値をここに定義します。各属性は type(値の型)を必ず持ち、必要に応じて source / selector / default を組み合わせます。
| キー | 説明 |
|---|---|
type | 値の型。string / number / integer / boolean / array / object / null を指定する |
default | 値が未設定のときに使われる初期値 |
source | 保存済みの HTML から値を読み戻す方法。省略するとブロックコメントに JSON として保存される |
selector | source を指定したとき、値を取り出す対象の要素を CSS セレクターで指定する。省略するとブロックのルート要素が対象 |
source の値によって、HTML のどこから値を読み取るかが変わります。
source | 読み取る場所 |
|---|---|
| 指定なし | HTML ではなく、ブロックコメント(<!-- wp:… {"level":3} -->)の中の JSON から読み取る |
"html" | selector で指定した要素の内側の HTML。太字やリンクを含む文章に使う |
"text" | selector で指定した要素のテキスト。タグは取り除かれる |
"attribute" | selector で指定した要素の属性値。取り出す属性名は attribute キーで指定する(例: 画像の src) |
たとえば次のように書くと、見出しテキストは .notice-box__heading 要素の中身から、画像の URL は img 要素の src 属性から読み戻され、isDismissible はブロックコメントに保存されます。
"attributes": {
"heading": {
"type": "string",
"source": "html",
"selector": ".notice-box__heading",
"default": ""
},
"imageUrl": {
"type": "string",
"source": "attribute",
"selector": "img",
"attribute": "src"
},
"isDismissible": {
"type": "boolean",
"default": false
}
}
ここで大切なのは、source を付けた属性は保存された HTML そのものが保存先になるという点です。ブロックを保存すると save 関数が返した HTML が投稿本文に書き出され、次にその投稿を開いたときは、selector をたどって値が復元されます。つまり save の出力に .notice-box__heading という要素が存在していなければ、いくら selector を書いても値は空のままです。
import { useBlockProps, RichText } from '@wordpress/block-editor';
export default function save( { attributes } ) {
const blockProps = useBlockProps.save( { className: 'notice-box' } );
return (
<div { ...blockProps }>
{/* selector に指定したクラスを save 側にも用意する */}
<RichText.Content
tagName="p"
className="notice-box__heading"
value={ attributes.heading }
/>
</div>
);
}
逆に source を付けない属性は HTML に現れず、ブロックコメントの中に JSON として書き込まれます。表示に使わない設定値(真偽値や選択肢など)は、こちらのほうが素直です。
supports でエディターの機能を追加する
supports は、WordPress が用意している標準機能をそのブロックで使うかどうかの指定です。自分で UI を書かなくても、値を書き加えるだけで色設定や余白設定のパネルがサイドバーに現れ、設定された値はクラス名やインラインスタイルとして自動的に出力されます。
| 項目 | 説明 |
|---|---|
html | 「HTML として編集」を許可するか。初期値は true。構造を崩されたくないブロックでは false にする |
anchor | true にすると、HTML アンカー(id 属性)の入力欄が追加される。初期値は false |
align | 配置の指定。true ですべての配置、[ "wide", "full" ] のように配列で許可する種類を限定できる |
color | 色設定の UI。background・text(いずれも初期値 true)、gradients・link(いずれも初期値 false)を持つオブジェクトで指定する |
spacing | 余白の UI。padding / margin / blockGap を true、または [ "top", "bottom" ] のように辺を限定して指定する |
typography | 文字まわりの UI。fontSize・lineHeight(いずれも初期値 false)を true にすると文字サイズ・行の高さを設定できる |
className | 初期値 true。wp-block-名前空間-ブロック名 というクラス名を自動で付与する |
customClassName | 初期値 true。サイドバーの「追加 CSS クラス」欄を表示する |
multiple | 初期値 true。false にすると1つの投稿に1回しか挿入できなくなる |
inserter | 初期値 true。false にするとインサーターの一覧に表示されない(子ブロックなどで使う) |
色や余白の値は、ブロックのルート要素に付くクラス名やスタイルとして保存されます。この出力を受け取るために、save 側では useBlockProps.save() が返す属性をルート要素に展開しておく必要があります。上の save.js のように { ...blockProps } を書いておけば、supports の設定はそのまま反映されます。
なお、余白やタイポグラフィなど一部の機能は、テーマ側の theme.json で該当の設定が無効になっていると、ブロックで true にしてもエディターに UI が出ないことがあります。設定パネルが現れないときは、ブロック側だけでなくテーマ側の設定も確認してください。
render を指定すると動的ブロックになる
投稿に保存された HTML をそのまま表示するのではなく、表示のたびにサーバー側で HTML を組み立てたいことがあります。最新の投稿一覧のように内容が変化するブロックがその代表です。こうしたブロックは動的ブロックと呼ばれ、block.json の render に PHP ファイルを指定するだけで実現できます。
"render": "file:./render.php"
指定した PHP ファイルの中では、ブロックの属性が入った $attributes、内側のブロックの出力である $content、ブロックのインスタンスである $block を使えます。ルート要素には get_block_wrapper_attributes() を出力しておくと、supports で設定された色や余白のクラスがフロント側にも反映されます。
<div <?php echo get_block_wrapper_attributes(); ?>>
<p class="notice-box__heading">
<?php echo esc_html( $attributes['heading'] ); ?>
</p>
</div>
動的ブロックでは、フロント側の HTML を PHP が担当するため、JavaScript 側の save は null を返して何も保存しないのが基本の形です。この場合、属性は HTML から読み戻せないので source は使わず、ブロックコメントに保存される形(source なし)で定義します。
block.json の全体例
ここまでの内容をまとめた block.json の例です。見出しを入力できる「お知らせボックス」ブロックを想定しています。
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "webool/notice-box",
"version": "1.0.0",
"title": "お知らせボックス",
"category": "text",
"icon": "megaphone",
"description": "見出しと本文をまとめて目立たせるお知らせ用のボックスです。",
"keywords": [ "notice", "お知らせ", "box" ],
"textdomain": "webool-blocks",
"attributes": {
"heading": {
"type": "string",
"source": "html",
"selector": ".notice-box__heading",
"default": ""
},
"isDismissible": {
"type": "boolean",
"default": false
}
},
"supports": {
"html": false,
"anchor": true,
"align": [ "wide", "full" ],
"color": {
"background": true,
"text": true
},
"spacing": {
"padding": true,
"margin": [ "top", "bottom" ]
},
"typography": {
"fontSize": true,
"lineHeight": true
}
},
"example": {
"attributes": {
"heading": "メンテナンスのお知らせ"
}
},
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"style": "file:./style-index.css"
}
example に書いた属性は、インサーターでブロックにマウスを乗せたときのプレビューに使われます。空のプレビューだと何のブロックか分かりづらいので、代表的な値を入れておくと親切です。
この block.json に対応する編集画面側のコードは次のようになります。edit.js では、定義した属性を attributes から受け取り、変更するときは setAttributes を呼びます。
import { useBlockProps, RichText } from '@wordpress/block-editor';
export default function Edit( { attributes, setAttributes } ) {
// block.json の attributes で定義した値を受け取る
const { heading } = attributes;
const blockProps = useBlockProps( { className: 'notice-box' } );
return (
<div { ...blockProps }>
<RichText
tagName="p"
className="notice-box__heading"
value={ heading }
onChange={ ( value ) => setAttributes( { heading: value } ) }
placeholder="見出しを入力"
/>
</div>
);
}
ブロックを登録する index.js では、block.json を読み込んでその name を使うのが定番の書き方です。名前を2か所に書かずに済むので、書き間違いを防げます。
import { registerBlockType } from '@wordpress/blocks';
import metadata from './block.json';
import Edit from './edit';
import save from './save';
// 第1引数に metadata.name(= webool/notice-box)を渡す
registerBlockType( metadata.name, {
edit: Edit,
save,
} );
block.json を編集しても変更が反映されないとき
タイトルやアイコンを変えたのにエディターの表示が変わらない、supports を足したのにパネルが増えない。block.json を触りはじめると、こうした「編集したのに反映されない」場面によく出会います。原因はだいたい次のどれかです。
WordPress が読んでいるのは src ではなくビルド後の block.json
いちばん多いのがこれです。register_block_type() に渡しているのは build ディレクトリなので、WordPress が読むのは build/block.json です。src/block.json を書き換えただけでは、ビルドを通すまで build 側は古い内容のまま残ります。編集後にビルド(または監視モードでの自動ビルド)が走っているか、build/block.json の中身が実際に更新されているかを確認してください。監視モードを起動したままでも、新しく作ったファイルは拾われないことがあるので、その場合は起動し直します。
name の書式が正しくないとブロックが登録されない
name は 名前空間/ブロック名 の形式で、英小文字・数字・ハイフンだけが使えます。noticeBox のように名前空間が抜けていたり、大文字やアンダースコアが混ざっていたりすると、ブロックの登録自体が失敗し、インサーターに何も出てきません。webool/notice-box のような形になっているか見直しましょう。
あわせて、JavaScript 側で registerBlockType() に渡している名前と、block.json の name が一致しているかも確認してください。両者がずれていると、PHP 側で登録されたブロックに対応する編集画面のコードが見つからず、エディターでブロックが正しく表示されません。上の index.js のように metadata.name を使えば、このずれは起きなくなります。
すでに保存した投稿でブロック検証エラーが出る
attributes の selector を変えたり、supports の変更にあわせて save の出力を変えたりすると、投稿に保存済みの HTML と、いまのコードが生成する HTML が食い違います。この状態で投稿を開くと「このブロックには、想定されていないエラーが含まれています」という検証エラーが表示され、内容がリカバリー待ちになります。
開発中で記事がまだ無いなら、そのブロックを一度削除して入れ直すのが手っ取り早い解決です。すでに公開済みの投稿で使っているブロックなら、以前の構造を deprecated として登録し、古い HTML も読めるようにしたうえで新しい形へ移行します。attributes と save は、公開後は気軽に変えられないものだと考えておくとよいでしょう。
JSON の書式そのものが壊れている
JSON では末尾のカンマやコメントが使えません。最後の項目のあとにカンマが残っている、値をシングルクォートで囲んでいる、といった書式の誤りがあると、ファイル全体が読み込めずブロックが登録されないままになります。エラーが画面に出ないぶん気づきにくいので、$schema を書いてエディターの検証を効かせておくと、こうしたミスをその場で見つけられます。
まとめ
block.json は、ブロックの名前・見た目・データ・読み込むファイルを1か所に宣言する設定ファイルです。PHP 側は register_block_type( __DIR__ . '/build' ) とディレクトリを渡すだけでよく、editorScript や style に書いたファイルは WordPress が適切な場面で読み込んでくれます。attributes ではブロックが持つ値を type と source で定義し、source を付けた属性は save が出力した HTML から selector をたどって読み戻されます。supports に項目を足すだけで色や余白の UI が増え、render に PHP ファイルを指定すればサーバー側で描画する動的ブロックになります。編集が反映されないときは、まずビルド後の block.json と name の書式を確認してみてください。