2026年7月15日
2026年7月15日
ACFのFlexible Contentの使い方(レイアウト設定とテンプレートでの表示)
Advanced Custom Fields(ACF)の Flexible Content(フレキシブルコンテンツ)フィールドを使うと、「見出し」「本文」「画像」などのレイアウト(部品)をあらかじめ用意しておき、編集する人がページごとに好きな順番・好きな数だけ並べられます。ランディングページや、セクションを積み重ねて作るページに向いています。
この記事では、Flexible Content フィールドの作り方と、テーマのテンプレートで表示するコードを説明します(2026年10月時点。表示のコードは Secure Custom Fields 6.9.7 と WordPress 6.9 で動作を確認しています)。
使える環境
- Flexible Content は ACF PRO の機能です。無料版の ACF には含まれていません。
- WordPress.org が配布している Secure Custom Fields(ACF から派生したプラグイン)にも Flexible Content があり、同じ関数(
have_rows()、get_row_layout()など)で表示できます。 - 表示のコードは、テーマの PHP テンプレートに書きます。ブロックテーマ(Twenty Twenty-Five など)は HTML のテンプレートでページを表示するため、以下の PHP のコードはクラシックテーマ(またはその子テーマ)の固定ページ用テンプレートに書く前提です。
手順1: Flexible Content フィールドを作る
- 管理画面の「ACF」→「フィールドグループ」(Field Groups)で、新しいフィールドグループを追加します。
- フィールドを追加し、フィールドタイプで「Flexible Content」を選びます。
- ラベル(例: ページのセクション)と、フィールド名(例:
page_sections)を入れます。フィールド名はテンプレートのコードで使います。 - フィールドグループの表示場所の設定(英語表示では Location Rules)で、表示する対象(例: 投稿タイプが固定ページ)を選んで保存します。
Flexible Content フィールドには、主に次の設定があります(ACF の公式ドキュメントより)。
| 設定 | 内容 |
|---|---|
| Layouts | 編集画面で選べるレイアウトの一覧 |
| Button Label | レイアウトを追加するボタンに表示する文字 |
| Minimum Layouts | 最低限必要なレイアウトの数 |
| Maximum Layouts | 追加できるレイアウトの上限 |
手順2: レイアウトとサブフィールドを用意する
レイアウトごとに、ラベル(Label)、名前(Name)、数の制限(Limit)、表示の形(Display)と、その中で使うフィールド(サブフィールド)を設定します。この記事では、次の 3 つのレイアウトを例にします。
| レイアウトの名前 | サブフィールド(名前・タイプ) | 用途 |
|---|---|---|
heading |
heading_text(テキスト) |
セクションの見出し |
text_block |
body(WYSIWYG エディター) |
本文 |
image_block |
image(画像) |
画像 |
- レイアウトの「名前」は、テンプレートで
get_row_layout()が返す値です。英数字とアンダースコアにしておくと、コードで扱いやすくなります。 - 画像フィールドの返り値の形式(英語表示では Return Format)は、画像の配列・URL・ID から選べます。この記事のコードでは 画像 ID を選びます。ID なら
wp_get_attachment_image()で、srcset付きのimgタグを出力できます。
保存したら、固定ページの編集画面を開きます。フィールドのボタンからレイアウトを追加し、順番を並べ替えられることを確認します。
手順3: テンプレートで表示する
固定ページ用のテンプレート(例: page.php やカスタムのページテンプレート)のループの中に、次のコードを書きます。
<?php
if ( have_rows( 'page_sections' ) ) :
while ( have_rows( 'page_sections' ) ) :
the_row();
$layout = get_row_layout();
if ( 'heading' === $layout ) {
printf( '<h2>%s</h2>', esc_html( get_sub_field( 'heading_text' ) ) );
} elseif ( 'text_block' === $layout ) {
echo '<div class="section-text">' . wp_kses_post( get_sub_field( 'body' ) ) . '</div>';
} elseif ( 'image_block' === $layout ) {
$image_id = get_sub_field( 'image' ); // 返り値の形式を「画像 ID」にしたフィールド
if ( $image_id ) {
echo wp_get_attachment_image( $image_id, 'large' );
}
}
endwhile;
endif;
have_rows()は、ページに追加されたレイアウトが残っている間trueを返します。the_row()で次のレイアウトに進み、get_row_layout()でそのレイアウトの名前を、get_sub_field()でサブフィールドの値を取り出します。- 出力するときはエスケープします。テキストは
esc_html()、HTML を含む WYSIWYG の値はwp_kses_post()を通します。 - テンプレートのループの外で使うときや、別のページの値を表示するときは、
have_rows( 'page_sections', $post_id )のように投稿 ID を渡します。
手順4: レイアウトごとにファイルを分ける
レイアウトが増えると、if の分岐が長くなります。レイアウトの名前と同じ名前のファイルをテーマに用意し、get_template_part() で読み込むと整理できます。
<?php
while ( have_rows( 'page_sections' ) ) :
the_row();
get_template_part( 'template-parts/flexible/' . get_row_layout() );
endwhile;
テーマの template-parts/flexible/heading.php には、そのレイアウトの表示だけを書きます。読み込んだファイルの中でも get_sub_field() で今の行の値を取り出せます。
<?php
// template-parts/flexible/heading.php
?>
<h2 class="section-heading"><?php echo esc_html( get_sub_field( 'heading_text' ) ); ?></h2>
同じように text_block.php、image_block.php を作ります。対応するファイルがないレイアウトは、何も表示されません。
手順5: 表示を確かめる
固定ページの編集画面で、レイアウトをいくつか追加して内容を入れ、保存してページを表示します。
- 追加した順番どおりに表示されるか
- 何も表示されない場合は、テンプレートのフィールド名(
page_sections)とレイアウトの名前が、ACF の設定と一字一句同じか - 画像の場所に何も出ない、または
Arrayと表示される場合は、画像フィールドの返り値の形式が「画像 ID」になっているか
運用での注意
- レイアウトの名前をあとから変えない: 保存済みのページには、変更前の名前でデータが残ります。名前を変えると、テンプレートの分岐に当たらなくなり、表示されなくなります。
- フィールドグループの設定を JSON で管理する: ACF の Local JSON(テーマに
acf-jsonフォルダーを作ると、フィールドグループの設定がファイルとして保存される機能)を使うと、本番と開発環境で設定をそろえやすくなります。 - ページあたりのレイアウト数に上限を設ける: Minimum Layouts・Maximum Layouts や、レイアウトごとの Limit で、編集する人が迷わない範囲に絞ります。
まとめ
- Flexible Content は ACF PRO(または Secure Custom Fields)の機能で、用意したレイアウトを編集する人がページごとに並べられる
- レイアウトの名前とサブフィールドの名前を決め、画像は返り値の形式を「画像 ID」にしておく
- テンプレートでは
have_rows()・the_row()・get_row_layout()・get_sub_field()で値を取り出し、esc_html()・wp_kses_post()でエスケープして出力する - レイアウトが増えたら
get_template_part()でレイアウトごとのファイルに分ける