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 フィールドを作る

  1. 管理画面の「ACF」→「フィールドグループ」(Field Groups)で、新しいフィールドグループを追加します。
  2. フィールドを追加し、フィールドタイプで「Flexible Content」を選びます。
  3. ラベル(例: ページのセクション)と、フィールド名(例: page_sections)を入れます。フィールド名はテンプレートのコードで使います。
  4. フィールドグループの表示場所の設定(英語表示では 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() でレイアウトごとのファイルに分ける

関連記事

お気軽にご相談ください

お見積りへ お問い合わせへ
▲