WordPressのブロックエディターでオリジナルブロックを作る方法

目次
  1. 確かめた環境
  2. 今回作る2つのブロック
  3. プラグインとHello Blockを作る
    1. create-blockを実行する
    2. 作られるファイル
  4. block.jsonにブロックの設定を書く
    1. 名前空間は最初に決める
  5. edit.jsとsave.jsで中身を書く
  6. CSSはstyle.scssに1回だけ書く
  7. ビルドしてブロックを入れてみる
  8. 文字を入力できるブロックを追加する
    1. –no-pluginでブロックだけ作る
    2. block.jsonにattributesを足す
    3. edit.jsにRichTextを置く
    4. save.jsでRichText.Contentを使う
    5. CSSはHello Blockと同じ
    6. ビルドして入力してみる
  9. PHPを書き換えなくても2つ目が登録される理由
  10. つまずきやすいところ
    1. save.jsを変えると、作ったブロックが壊れる
    2. block.jsonのファイル名はビルド後の名前
    3. –no-pluginはsrcの中で実行する
    4. selectorとsave.jsのタグを合わせる
  11. 公式のドキュメントとサンプル
  12. おわり

ブロックエディター(Gutenberg)のブロック一覧に、自分で作ったブロックを並べられるようになります。

今回作るのは、オレンジの背景に白い文字が入ったブロックです。決まった文章を出すだけのものと、その場で文字を入力できるものの2つを作ります。

オレンジ背景・白文字のオリジナルブロックがエディターに2つ並んでいる画面

使うのは@wordpress/create-blockという公式のツールです。コマンドを1行打つと、ブロックに必要なファイルが一式そろいます。あとは中身を書き換えるだけ!

自作ブロックと聞くと難しそうに感じるかもしれませんが、思っているより簡単です。いっしょに作っていきましょう!

確かめた環境

この記事のコードと手順は、次の環境で実際に動かして確かめています。

項目バージョン
WordPress7.1.2(テーマはTwenty Twenty-Five・PHP 8.3)
Node.js / npm22.20.0 / 11.11.0
@wordpress/create-block4.100.0
@wordpress/scripts35.0.0(create-blockが入れたもの)

準備しておくのは次の2つです。

必要なもの目安
Node.js22.13以上(create-block 4.100.0の要件)
ローカルのWordPress6.8以上(作られるプラグインのRequires at leastが6.8)

今回作る2つのブロック

1つのプラグイン(Hello Block)の中に、ブロックを2つ入れます。

ブロック名前できること
Hello Blockmy-gutenberg/hello-block「Hello World, Pタグのコンテンツです。」という決まった文章を出す
Editable Blockmy-gutenberg/editable-block同じ見た目で、文字を自由に入力できる

汎用性は無いかもしれませんが、作り方の基礎を学ぶうえでは最適です。2つを見比べると「文字を入力できるようにするには、どこを足せばいいか」がよく分かると思います。

プラグインとHello Blockを作る

独自のブロックは、プラグインとして作るのが一般的です。create-blockがプラグインごと作ってくれます。

create-blockを実行する

まず、ローカル環境のwp-content/pluginsフォルダに移動します。

cd wp-content/plugins

移動したら、次のコマンドを実行します。

npx @wordpress/create-block@latest hello-block --namespace my-gutenberg --title "Hello Block" --category text

初回は@wordpress/scriptsのインストールで数分かかります…。最後にDone: WordPress plugin Hello Block bootstrapped ...と出れば完了です。

この時点で、管理画面のプラグイン一覧に「Hello Block」が出てきます。有効化しておきましょう。

作られるファイル

node_modulesを除くと、こんな感じのファイルができています。

hello-block/
├── hello-block.php        … プラグイン本体(ブロックを登録するPHP)
├── package.json           … npm start / npm run build などのコマンド
├── readme.txt
├── src/
│   └── hello-block/
│       ├── block.json     … ブロックの設定(名前・アイコン・カテゴリー・読み込むファイル)
│       ├── index.js       … ブロックを登録するJS
│       ├── edit.js        … エディターでの見た目
│       ├── save.js        … 保存されるHTML
│       ├── style.scss     … エディターとサイトの両方に効くCSS
│       ├── editor.scss    … エディターだけに効くCSS
│       └── view.js        … サイト表示で動かすJS(今回は使わない)
└── build/                 … npm run buildで作られる完成品(WordPressが読むのはこっち)

書き換えるのはsrc/hello-block/の中だけです。hello-block.phpとindex.jsは、生成されたまま触りません。

ちなみに、index.jsはコメントを除くとこれだけです。

import { registerBlockType } from '@wordpress/blocks';
import './style.scss';
import Edit from './edit';
import save from './save';
import metadata from './block.json';

registerBlockType( metadata.name, {
	edit: Edit,
	save,
} );

名前やアイコンはblock.jsonから読むので、JS側は「エディターでの見た目(edit)」と「保存するHTML(save)」を渡すだけになっています。

block.jsonにブロックの設定を書く

ブロックの名前・アイコン・カテゴリーなどは、block.jsonにまとめて書きます。src/hello-block/block.jsonを次のように書き換えます。

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 3,
	"name": "my-gutenberg/hello-block",
	"version": "0.1.0",
	"title": "Hello Block",
	"category": "text",
	"icon": "universal-access-alt",
	"description": "決まった文章を表示するだけのブロックです。",
	"example": {},
	"supports": {
		"html": false
	},
	"textdomain": "hello-block",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css"
}

生成されたものから変えたのは3か所です。iconをsmileyからuniversal-access-altに、descriptionを日本語に、viewScriptの行を削除(サイト表示でJSを動かさないため)。

主な項目の意味は次のとおりです。

項目意味
nameブロックの名前。名前空間/ブロック名の形
titleブロック挿入画面に出る名前
category挿入画面のどの見出しに入るか。text / media / design / widgets / theme / embed
iconDashiconsの名前(dashicons-を除いた部分)
description挿入画面でマウスを乗せたときの説明
example挿入画面のプレビューを出すための設定({}でも出る)
apiVersion3にしておく(生成時から3)
editorScript / editorStyle / style読み込むファイル

アイコンの一覧は公式のページで確認できます。

Dashicons | WordPress Developer Resources

名前空間は最初に決める

ブロックを作るときに重要なのが、名前空間を指定することです。複数のブロック系プラグインを使うときに、名前がかぶるのを防ぐためですね。

今回はmy-gutenbergを名前空間にして、my-gutenberg/hello-blockというブロック名にしています。

nameはあとから変えると、そのブロックを使った記事が壊れます。 最初に決めておきましょう。

edit.jsとsave.jsで中身を書く

ブロックの中身は、エディターでの見た目(edit.js)と、保存されるHTML(save.js)の2つに分けて書きます。

src/hello-block/edit.jsはこちらです。

import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';

// エディターの中での見た目。
export default function Edit() {
	return <p { ...useBlockProps() }>Hello World, Pタグのコンテンツです。</p>;
}

src/hello-block/save.jsはこちらです。

import { useBlockProps } from '@wordpress/block-editor';

// 保存される HTML(=サイトに表示される HTML)。
// edit.js と同じ見た目になるように書く。
export default function save() {
	return (
		<p { ...useBlockProps.save() }>Hello World, Pタグのコンテンツです。</p>
	);
}

一番外のタグにuseBlockProps()(エディター用)とuseBlockProps.save()(保存用)を付けると、wp-block-my-gutenberg-hello-blockというクラスが自動で付きます。

クラス名は.wp-block-[名前空間]-[ブロック名]の形です。このクラスにCSSを当てていきます。

CSSはstyle.scssに1回だけ書く

src/hello-block/style.scssに、オレンジの背景と白い文字を書きます。

/**
 * エディターとサイト表示の両方に効くスタイル。
 */
.wp-block-my-gutenberg-hello-block {
	background-color: #efa336;
	color: #fff;
	padding: 16px;
}

style.scssはエディターとサイトの両方に効きます。なので、共通のCSSはここに1回書くだけでOKです!

src/hello-block/editor.scssは生成されたまま(コメントだけ日本語に)にしています。

/**
 * エディターの中だけに効くスタイル。
 */
.wp-block-my-gutenberg-hello-block {
	border: 1px dotted #f00;
}

editor.scssには「エディターでだけ枠を出す」のような、エディターとの差分だけを書きます。

ビルドしてブロックを入れてみる

書き換えたら、プラグインのフォルダ(hello-block/)に移動します。

cd hello-block

移動したら、ビルドします。

npm run build

書きながら確かめるときはnpm startが便利です。保存するたびに自動でビルドされます。

投稿の編集画面でブロック挿入画面を開くと、「テキスト」の最後にHello Blockが出てきます。マウスを乗せると、プレビューと説明文も出ます!

ブロック挿入画面の「テキスト」にHello Blockが表示され、プレビューが出ている画面

選ぶと、オレンジのブロックが挿入されます。保存してサイトを表示すると、作ったブロックの内容で反映されているのが分かるはずです。

サイト表示でオレンジ背景・白文字のブロックが表示されている画面

保存されたHTMLはこんな感じです。

<!-- wp:my-gutenberg/hello-block -->
<p class="wp-block-my-gutenberg-hello-block">Hello World, Pタグのコンテンツです。</p>
<!-- /wp:my-gutenberg/hello-block -->

CSSはサイト側にインラインで出力されていました。エディター用のCSSとJSはサイト側には出ません。

文字を入力できるブロックを追加する

では、同じプラグインに2つ目のブロックを足していきます。今度は、エディターの中で文字を入力できるブロックです。

–no-pluginでブロックだけ作る

プラグインのフォルダ(hello-block/)の中にいる状態から、srcフォルダに移動します。

cd src

移動したら、もう一度create-blockを実行します。

npx @wordpress/create-block@latest editable-block --no-plugin --namespace my-gutenberg --title "Editable Block" --category text --textdomain hello-block

終わったら、プラグインのフォルダに戻ります。

cd ..
オプション意味
--no-pluginプラグイン一式ではなく、ブロックのファイルだけを今いるフォルダに作る
--textdomain hello-block翻訳用の名前をプラグインに揃える(付けないとeditable-blockになる)

src/editable-block/ができて、中身はHello Blockと同じ7ファイルです。

block.jsonにattributesを足す

入力した文字を覚えておくために、block.jsonにattributes(ブロックが覚えておく値)を追加します。src/editable-block/block.jsonはこちらです。

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 3,
	"name": "my-gutenberg/editable-block",
	"version": "0.1.0",
	"title": "Editable Block",
	"category": "text",
	"icon": "edit",
	"description": "文字を入力できるブロックです。",
	"example": {
		"attributes": {
			"content": "ここに文字を入力できます。"
		}
	},
	"attributes": {
		"content": {
			"type": "string",
			"source": "html",
			"selector": "p"
		}
	},
	"supports": {
		"html": false
	},
	"textdomain": "hello-block",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css"
}

生成されたものから変えたのは、icon(edit)、description、exampleの入力例、attributesの追加、viewScriptの削除です。

attributesの読み方は次のとおりです。

項目意味
content値の名前(自由に付けてよい。edit.js / save.jsでattributes.contentとして使う)
"type": "string"値は文字列
"source": "html"値は、保存されたHTMLの中から取り出す
"selector": "p"取り出す場所は<p>の中身。save.jsで出すタグと合わせる

基本的には、selectorの項目だけHTMLタグを合わせてあげればOKかと思います。

edit.jsにRichTextを置く

テキストを入力させるには「RichText」を使います。src/editable-block/edit.jsはこちらです。

import { useBlockProps, RichText } from '@wordpress/block-editor';
import './editor.scss';

// エディターの中での見た目。
// RichText を置くと、その場で文字を入力できるようになる。
export default function Edit( { attributes, setAttributes } ) {
	return (
		<RichText
			{ ...useBlockProps() }
			tagName="p"
			value={ attributes.content }
			onChange={ ( content ) => setAttributes( { content } ) }
			placeholder="ここに文字を入力"
		/>
	);
}

tagName="p"を渡すと、<p>がそのまま入力欄になります。太字・リンクなどのツールバーも自動で付きます!

入力するたびにonChangeが呼ばれて、setAttributesでcontentに保存されます。Reactでよく見る書き方ですが、こういう書き方だと捉えておけばひとまずはいいと思います。

save.jsでRichText.Contentを使う

src/editable-block/save.jsはこちらです。

import { useBlockProps, RichText } from '@wordpress/block-editor';

// 保存される HTML(=サイトに表示される HTML)。
// 入力された文字(attributes.content)を <p> の中に書き出す。
export default function save( { attributes } ) {
	return (
		<RichText.Content
			{ ...useBlockProps.save() }
			tagName="p"
			value={ attributes.content }
		/>
	);
}

保存するときはRichText.Contentで<p>に書き出します。次に開いたときは、block.jsonのsource: html / selector: pの指示で、<p>の中身をcontentに読み戻します。

この往復がそろっているから、ブロックが壊れないんですね。

CSSはHello Blockと同じ

style.scssとeditor.scssは、クラス名をeditable-blockに変えるだけです。

/**
 * エディターとサイト表示の両方に効くスタイル。
 */
.wp-block-my-gutenberg-editable-block {
	background-color: #efa336;
	color: #fff;
	padding: 16px;
}
/**
 * エディターの中だけに効くスタイル。
 */
.wp-block-my-gutenberg-editable-block {
	border: 1px dotted #f00;
}

ビルドして入力してみる

プラグインのフォルダで、もう一度ビルドします。

npm run build

挿入画面にEditable Blockが増えています。入れてみると、オレンジのブロックの中にそのまま文字を入力できます!

Editable Blockに文字を入力している編集画面

太字にした文字も、保存して表示するところまで反映されました。保存してから再読み込みしても、ブロックは壊れていません。

保存して再読み込みしたあとの編集画面。2つのブロックがそのまま残っている

保存されたHTMLはこんな感じです。

<!-- wp:my-gutenberg/editable-block -->
<p class="wp-block-my-gutenberg-editable-block">ここは自由に書き換えられます。<strong>太字もOK</strong></p>
<!-- /wp:my-gutenberg/editable-block -->

ここまで実装できると、ブロックを作っている実感がわいてきますね。

PHPを書き換えなくても2つ目が登録される理由

2つ目のブロックを足したのに、PHPは1行も書き換えていません。生成されたhello-block.phpの中で、ブロックを登録しているのはこの部分です。

function my_gutenberg_hello_block_block_init() {
	wp_register_block_types_from_metadata_collection( __DIR__ . '/build', __DIR__ . '/build/blocks-manifest.php' );
}
add_action( 'init', 'my_gutenberg_hello_block_block_init' );

これはbuild/の中のブロックを全部まとめて登録する1行です。block.jsonを置いてビルドすれば、そのブロックが登録されます。

ブロックを増やしても、このPHPは変えなくていいんです。めちゃくちゃ楽です!

つまずきやすいところ

save.jsを変えると、作ったブロックが壊れる

保存済みのHTMLと、今のsave.jsが出すHTMLが1文字でも違うとエラーになります。

試しにsave.jsの文言だけ「です!」に変えてビルドすると、すでに入れていたブロックにこう表示されました。

「このブロックには、想定されていないか無効なコンテンツが含まれています。」と表示されたブロック

「このブロックには、想定されていないか無効なコンテンツが含まれています。」

edit.jsは変えても壊れません。公開後にsave.jsを変えたいときは、deprecated(古いsaveを残しておく仕組み)を使います。

ちなみに、2020年にこの記事を書いたときは、attributesを指定せずにリロードして同じメッセージが出てブロックが消えました…。文字を入力できるブロックでは、attributesの指定を忘れないようにしましょう!

block.jsonのファイル名はビルド後の名前

file:./のあとに書くのは、ビルド後のファイル名です。

書くファイルビルド後の名前
style.scssstyle-index.css
editor.scssindex.css

–no-pluginはsrcの中で実行する

プラグインのフォルダ直下で実行すると、srcの外にできてビルドされません。

selectorとsave.jsのタグを合わせる

tagName="h2"に変えたら、block.jsonのselectorもh2に変えます。

公式のドキュメントとサンプル

もっと詳しく知りたいときは、公式のドキュメントが参考になります。

WordPress公式がサンプルのプラグインもまとめてくれています。こちらもぜひ参考にしてみてください。

WordPress/block-development-examples(GitHub)

おわり

WordPressのブロックエディターで、block.jsonを使ってオリジナルブロックを作る方法でした。

create-blockで一式を作り、block.json・edit.js・save.js・style.scssを書き換えてビルドする。この流れさえ覚えれば、ブロックを何個増やしてもPHPは触らなくて大丈夫です。

決まった文章を出すだけのブロックは使う場面が少ないかもしれませんが、文字を入力できるブロックまで作れると、一気に使いみちが広がると思います。ぜひ自分のブロックを作ってみてください!

WordPressでお悩みの方はお気軽にご相談ください。

ちょっとしたお困り事からサイト全体のリニューアルのようなご依頼まで、お悩みに応じて柔軟に対応いたします。

この記事を書いた人

はにわまん

HPcode代表。300件以上のWordPress案件を対応してきました。ちょっとしたWordPressのカスタマイズからブロックテーマでのリニューアルまで。更新できるWordPressサイトが好きです。