ブロックエディター(Gutenberg)のブロック一覧に、自分で作ったブロックを並べられるようになります。
今回作るのは、オレンジの背景に白い文字が入ったブロックです。決まった文章を出すだけのものと、その場で文字を入力できるものの2つを作ります。

使うのは@wordpress/create-blockという公式のツールです。コマンドを1行打つと、ブロックに必要なファイルが一式そろいます。あとは中身を書き換えるだけ!
自作ブロックと聞くと難しそうに感じるかもしれませんが、思っているより簡単です。いっしょに作っていきましょう!
確かめた環境
この記事のコードと手順は、次の環境で実際に動かして確かめています。
| 項目 | バージョン |
|---|---|
| WordPress | 7.1.2(テーマはTwenty Twenty-Five・PHP 8.3) |
| Node.js / npm | 22.20.0 / 11.11.0 |
| @wordpress/create-block | 4.100.0 |
| @wordpress/scripts | 35.0.0(create-blockが入れたもの) |
準備しておくのは次の2つです。
| 必要なもの | 目安 |
|---|---|
| Node.js | 22.13以上(create-block 4.100.0の要件) |
| ローカルのWordPress | 6.8以上(作られるプラグインのRequires at leastが6.8) |
今回作る2つのブロック
1つのプラグイン(Hello Block)の中に、ブロックを2つ入れます。
| ブロック | 名前 | できること |
|---|---|---|
| Hello Block | my-gutenberg/hello-block | 「Hello World, Pタグのコンテンツです。」という決まった文章を出す |
| Editable Block | my-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 |
icon | Dashiconsの名前(dashicons-を除いた部分) |
description | 挿入画面でマウスを乗せたときの説明 |
example | 挿入画面のプレビューを出すための設定({}でも出る) |
apiVersion | 3にしておく(生成時から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が出てきます。マウスを乗せると、プレビューと説明文も出ます!

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

保存された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が増えています。入れてみると、オレンジのブロックの中にそのまま文字を入力できます!

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

保存された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.scss | style-index.css |
| editor.scss | index.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は触らなくて大丈夫です。
決まった文章を出すだけのブロックは使う場面が少ないかもしれませんが、文字を入力できるブロックまで作れると、一気に使いみちが広がると思います。ぜひ自分のブロックを作ってみてください!


