WordPressブロックエディタで作る自作カスタムブロック入門ガイド

WordPressのブロックエディタ(Gutenberg)は、標準で提供されるブロックだけでも多彩な表現が可能ですが、自分だけのカスタムブロックを作成することで、さらに可能性は広がります。本記事では、WordPressブロックエディタで自作ブロックを作成する方法を、初心者にもわかりやすく解説します。プログラミングの基礎知識があれば、誰でもチャレンジできる内容となっています。

この記事内ではWordPress公式による@wordpress/create-blockパッケージのインストールを前提に説明しています。

目次を読み込み中…

カスタムブロックのファイル構造

WordPressのGutenbergブロックエディタでカスタムブロックを開発する際、適切なファイル構造を理解することが成功への第一歩です。カスタムブロック開発は一見複雑に思えるかもしれませんが、基本的な構造を把握すれば、効率的に開発を進めることができます。

Gutenbergブロックの基本構成要素

ブロック開発では、JavaScriptファイル、CSSファイルが連携して動作します。要素を適切に組み合わせることで、機能的なブロックを作成することが可能となります。

典型的なファイル構成は次の通りです:

ファイル構成
my-custom-block/
├── block.json          # ブロック設定ファイル
├── index.js            # メインのJavaScriptファイル
├── edit.js             # 編集用コンポーネント
├── save.js             # 保存用コンポーネント
├── view.js             # フロントエンド用のJavaScriptファイル
├── editor.scss         # エディタ用のスタイル
└── style.scss          # エディタとフロントエンド共通のスタイル

Gutenbergブロックを構成する核は「編集用コンポーネント(Edit)」と「保存用コンポーネント(Save)」です。これらはReactコンポーネントとして実装され、それぞれ異なる役割を持っています。

編集用コンポーネントは、WordPress管理画面上でのブロックの見た目と操作性を定義します。ユーザーがブロックを操作する際のインターフェースとなり、テキスト入力フィールドやメディア選択ボタンなど、編集に必要な要素をここに実装します。

保存用コンポーネントは、そのブロックが実際にWebサイト上でどのように表示されるかを定義します。

ファイル間の関係性と依存関係

カスタムブロック開発では、各ファイルが互いにどのように関連し、依存しているかを理解することが非常に重要です。

中心となるのは「block.json」ファイルで、これがブロック全体の設定と各ファイルの関係性を定義します。

index.js」はブロックのJavaScript部分のエントリーポイントであり、ブロックの登録処理を担当します。このファイル内で「edit.js」と「save.js」からそれぞれ関数をインポートして使用します。「edit.js」は管理画面でのブロックの編集インターフェースを定義し、「save.js」はコンテンツ保存時に生成されるHTMLを定義します。

view.js」はフロントエンド専用のJavaScriptファイルで、公開ページでのみ実行されます。このファイルは他のJavaScriptファイルとは独立しており、「save.js」で生成されたHTMLに対して動的な機能を追加するために使用されます。

スタイルファイルについては、「editor.scss」は管理画面のエディタでのみ適用されるスタイルを定義し、「style.scss」はエディタと公開ページの両方で適用されるスタイルを定義します。

これらのファイル間の依存関係と役割分担を理解することで、効率的なブロック開発が可能になります。例えば、ブロックの外観を変更したい場合は「style.scss」を、編集インターフェースのみを変更したい場合は「editor.scss」と「edit.js」を、保存されるHTMLを変更したい場合は「save.js」を修正するというように、目的に応じて適切なファイルを編集することができます。

block.jsonの設定項目

block.jsonファイルには、ブロックの基本情報から動作に関する詳細設定まで、様々な情報が含まれています。

基本的な構文は次の通りです:

json
{
    "$schema": "https://schemas.wp.org/trunk/block.json",
    "apiVersion": 3,
    "name": "name-space/block-name",
    "version": "1.0.0",
    "title": "ブロックの名称",
    "category": "text",
    "icon": "smiley",
    "description": "",
    "example": {},
    "supports": {
        "html": false
    },
    "textdomain": "block-name",
    "editorScript": "file:./index.js",
    "editorStyle": "file:./index.css",
    "style": "file:./style-index.css",
    "viewScript": "file:./view.js"
}

"$schema":JSONスキーマの参照先を指定するもので、エディタでの入力補完やバリデーションに役立ちます。
基本的にデフォルトから変更は不要です

"apiVersion":使用するブロックAPIのバージョンを指定します。WordPress 6.3以降ではこのバージョン3が利用可能となり、最新の機能にアクセスできます。基本的にデフォルトから変更は不要です

"name":ブロックの一意の識別子であり、命名規則として「名前空間/ブロック名」の形式を取ります。この例では「name-space」が名前空間、「block-name」がブロック名です。この識別子はHTML出力時のdata-block属性にも使用されます。

"version":ブロックのバージョン番号を示し、更新管理に役立ちます。特にブロックライブラリとして公開する場合には重要な情報となります。

"title":エディター画面に表示される名前です。分かりやすく、かつブロックの機能を端的に表す名前をつけることが推奨されます。

"category":エディター画面での分類カテゴリを指定します。標準では「text」、「media」、「design」、「widgets」、「theme」などが用意されています。

"icon":エディター画面に表示されるアイコンを指定します。Dashiconsの名前を文字列で指定するか、SVGデータをオブジェクトで指定することができます。

Dashiconsの名前確認方法

以下からアイコンを選択し、URLを確認してください。
#より後ろの部分が名前になります。

"description":ブロックの詳細な説明文で、サイドバーなどに表示されます。

"example":ブロックプレビューのサンプルデータを定義します。空のオブジェクトを指定した場合は、デフォルト属性値を使用したプレビューが表示されます。

"supports":ブロックの機能を指定します。例として設定されている "html": false は、ブロックエディタのHTMLモードでの直接編集を無効にする設定です。その他にも多様なサポート設定が可能です。

"textdomain":ブロック内のテキストの翻訳用ドメインを指定します。

"editorScript":エディター画面で使用されるJavaScriptファイルのパスを指定します。

"editorStyle":エディタ内でのみ適用されるCSSファイルのパスを指定します。

"style":エディタとフロントエンド両方で適用されるCSSファイルのパスを指定します。

"viewScript":フロントエンドでのみ実行されるJavaScriptファイルのパスを指定します。

これらの設定項目を適切に構成することで、WordPressはブロックを正確に識別し、必要なリソースを適切なタイミングで読み込むことができます。block.jsonを介したこの宣言的なアプローチにより、コードの見通しが良くなり、メンテナンス性も向上します。

さらに詳細な設定情報は以下から確認できます:

シンプルなカスタムブロック作成

カスタムブロックの基本構造を理解したところで、実際にシンプルなカスタムブロックを作成してみましょう。ここでは、タイトルが付いているテキストボックスを例に解説します。

block.json

json
{
    "$schema": "https://schemas.wp.org/trunk/block.json",
    "apiVersion": 3,
    "name": "my-block/titlebox",
    "title": "タイトル付ボックス",
    "category": "text",
    "icon": "smiley",
    "description": "タイトルが付いているテキストボックス",
    "supports": {
        "html": false
    },
    "attributes": {
        "title": {
            "type": "string",
            "selector": "span",
            "default": ""
        }
    },
    "textdomain": "titlebox",
    "editorScript": "file:./index.js",
    "editorStyle": "file:./index.css",
    "style": "file:./style-index.css",
    "viewScript": "file:./view.js"
}
変数の定義

attributesでブロック内で使用する変数定義を追加しています。

  • title:変数名(今回は「title」と定義)
  • type:変数の型
  • selector:変数を組み込むタグ
  • default:変数の初期値

index.js

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,
} );
インポート

@wordpress/blocksからregisterBlockType関数をインポートしています。

./style.scssをインポートすることで、フロントエンドとエディタの両方で使用されるスタイルを読み込んでいます。このインポートはビルドによって処理され、CSSファイルとして出力されます。

./edit./saveからそれぞれ編集用と保存用のコンポーネントをインポートしています。

./block.jsonからメタデータをインポートしています。これによりブロックの基本情報を一箇所で管理できます。

登録

インポートしたregisterBlockType関数を呼び出して、新しいブロックタイプを登録しています。

edit.js

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

export default function Edit( { attributes, setAttributes } ) {
    const { title } = attributes;
    const blockProps = useBlockProps({
        className: 'myblock-titlebox'
    });
    const updateTitle = (newTitle) => {
        setAttributes({ title: newTitle });
    };
    return (
        <section {...blockProps}>
            <div className="title">
                <RichText
                    tagName="span"
                    onChange={updateTitle}
                    value={title}
                    placeholder="タイトルを入力..."
                />
            </div>
            <div className="content">
                <InnerBlocks 
                    template={['core/paragraph']}
                    templateLock={false}
                />
            </div>
        </section>
    );
}
インポート

@wordpress/block-editorからuseBlockPropsRichTextInnerBlocksコンポーネントをインポートしています。

./editor.scssをインポートして、エディタ専用のスタイルを適用します。

関数コンポーネントの定義

attributessetAttributesをオブジェクトとして受け取ります。

  • attributes: ブロックの現在の状態を含むオブジェクト
  • setAttributes: ブロックの状態を更新するための関数
関数の定義

const { title } = attributes;で、ブロックの属性からtitle値を取り出しています。

useBlockPropsフックを使って、ブロックに必要なプロパティを生成しています。 classNameオプションでブロックにカスタムクラス名を追加しています。

updateTitle関数は、ユーザーがタイトルを編集したときに呼び出され、setAttributesを使ってtitle属性を更新します。

ブロックエディタの出力要素

section要素をルートとして、タイトル部分とコンテンツ部分の2つのdivを含む構造を返しています。

タイトル部分にはRichTextコンポーネントを使用しています。これにより、ユーザーはリッチテキスト編集機能を使ってタイトルを編集できます。
オプションで各種設定を変更しています:

  • tagName="span": 出力されるHTML要素をspanに指定
  • onChange={updateTitle}: テキスト変更時、事前に定義したupdateTitleを呼び出し
  • value={title}: 表示するテキストを変数titleに指定
  • placeholder="タイトルを入力...": 空の場合に表示されるプレースホルダーテキスト

コンテンツ部分にはInnerBlocksコンポーネントを使用しています。これにより、ブロック内に他のブロックを入れ子にできます。
オプションで各種設定を変更しています:

  • template={['core/paragraph']}: 初期状態で挿入されるブロックのテンプレートを段落ブロックに指定
  • templateLock={false}: テンプレートのロックを解除し、ユーザーが自由にブロックを追加・削除可能に設定

save.js

save.js
import { useBlockProps, RichText, InnerBlocks } from "@wordpress/block-editor";

export default function save({ attributes }) {
    const { title } = attributes;
    const blockProps = useBlockProps.save({
        className: 'myblock-titlebox'
    });
	return (
        <section {...blockProps}>
            <div className="title">
                <RichText.Content
                    tagName="span"
                    value={title}
                />
            </div>
            <div className="content">
                <InnerBlocks.Content />
            </div>
        </section>
	);
}
インポート

@wordpress/block-editorからuseBlockPropsRichTextInnerBlocksコンポーネントをインポートしています。これらはブロックの保存時に必要なコンポーネントです。

関数コンポーネントの定義

setAttributesをオブジェクトとして受け取ります。

関数の定義

const { title } = attributes;で、ブロックの属性からtitle値を取り出しています。

useBlockProps.saveメソッドを使って、フロントエンド用のプロパティを生成しています。 classNameオプションでブロックにカスタムクラス名を追加しています。

ブロックエディタの保存要素

section要素をルートとして、タイトル部分とコンテンツ部分の2つのdivを含む構造を返しています。

タイトル部分にはRichText.Contentコンポーネントを使用しています。これはRichTextの保存用バージョンです。
オプションで各種設定を変更しています:

  • tagName="span": 出力されるHTML要素をspanに指定
  • value={title}: 表示するテキストを変数titleに指定

コンテンツ部分にはInnerBlocks.Contentコンポーネントを使用しています。これはInnerBlocksの保存用バージョンです。

保存時にはもう値の更新は行わないため、変更関係のプロパティや関数は含まれません

view.js

今回は不要なので中身はすべて削除で問題ありません。

editor.scss/style.scss

useBlockPropsを使うことで自動的にブロックの名前を元にしたクラスが設定されます。

ブロック名:my-block/titlebox
クラス名 :wp-block-my-block-titlebox

便利ですが、クラス名が長くなりがちでわかりにくいため、オプションで追加したClassNameの使用を推奨します。

css
.myblock-titlebox {
    // スタイルの記述
}

カスタムブロック開発の次のステージへ

基本的なカスタムブロック開発を理解したら、次はより高度な機能の実装に挑戦してみましょう。カスタムブロックの真の力は、WordPress標準のブロックでは実現できない、サイト独自の機能や表現を可能にすることにあります。

次のステップとして考えられるのは、より多彩なコントロールやインターアクティブな要素の追加です。例えば、カラーの選択、フォントサイズの選択、アニメーション効果の設定、条件付き表示機能などを実装することができます。また、APIと連携してダイナミックなコンテンツを表示するブロックも、高度な使用例の一つです。

さらに、ブロックバリエーションやブロックパターンの作成にも挑戦してみるとよいでしょう。これにより、一つのブロックから複数のスタイルやレイアウトを提供したり、複数のブロックを組み合わせた再利用可能なパターンを作成したりすることができます。

WordPress開発者ドキュメントやコミュニティフォーラムを定期的にチェックし、新しい機能や改善されたAPI、ベストプラクティスなどを学び続けましょう。継続的な学習と実践により、あなたのWordPressサイトをさらに強力で独自性のあるものにすることができるでしょう。

この記事は役に立ちましたか?

もし参考になりましたら、下記のボタンで教えてください。

関連記事

コメント

この記事へのコメントはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)