DICE Project

BLOG

Web制作
【WordPress】ACF PRO をつかってカスタムブロックを作成! その2

うちのこをしゃべらせるカスタムブロックを作りました。

ハルカ
わぁい!
カイ
これで俺らもしゃべり放題★
ハルカ
やったね!

かわいいね!!勝ちです!!
✌(‘ω’✌)三✌(‘ω’)✌三(✌’ω’)✌

前回記事がなにやらそこそこ見られているらしく…。

またなんか作ってみるかー!
というのと、あとは昔のノリでうちのこをしゃべらせようと思ったので

あらためて、ACF PRO をつかってカスタムブロックを作る手順のメモです。

⓪:下準備

前回のハマりポイント。テーマフォルダに acf-json フォルダを作成しておきます。
この状態で、ACFでフィールドを保存すると、この中にJSON形式の設定ファイルがポコポコ蓄積されていきます。(ここの中身は編集の必要なし)

①:functions.phpでカスタムブロックの登録

functions.php に書いてアップ。

/* --------------------------------------------
 * カスタムブロックの登録
 * -------------------------------------------- */
add_action('init', 'register_acf_blocks');
function register_acf_blocks()
{
  register_block_type(dirname(__FILE__, 2) . '/blocks/charaspeech'); //※1
}

/* --------------------------------------------
 * ACFブロックカテゴリーの登録 //※2
 * -------------------------------------------- */
function add_block_categories($categories, $post)
{

  $add_categories = [
    [
      'slug' => 'dp-custom-blocks',
      'title' => 'DPカスタムブロック',
      'icon' => 'star-filled',
    ],
  ];
  $categories = array_merge($add_categories, $categories);
  return $categories;
}
add_filter('block_categories_all', 'add_block_categories', 10, 2);

/* --------------------------------------------
 * ブロックを使用するときのみCSSを読み込む
 * -------------------------------------------- */
add_action('init', 'custom_block_styles');
function custom_block_styles()
{
  wp_enqueue_block_style(
    'acf/charaspeech',
    array(
      'handle' => 'dp-customblock',
      'src' => home_url('/css/customblock.css'), //※3
    )
  );
}

※1:テーマフォルダに blocks フォルダを作成、さらに charaspeech フォルダを作成して、その中にもろもろ設定ファイルを入れる構成です

※2:デフォルトのブロックリストに混ぜたくなかったので、独自のカテゴリを作成することにしました
(独自のカテゴリを作成すると、記事編集画面の左側のブロックリストには ←このような形で出てきます)

※3:blocks フォルダ > 各ブロック用のフォルダ にCSSを入れる例を見かけますが、このサイトでは、自作ブロック用のスタイルは、まとめて /css/customblock.css に入れています。
ちなみに、サイト全体が「ブロックテーマ」で作られていないと、「ブロックを使用しているときのみ読込み」はできないっぽいです…。(このサイトは、記事以外にはブロックを使わない「クラシックテーマ」タイプなので、どのページでも読み込まれてしまう模様)
とにかくカスタムブロック用のCSSの登録は必要なので、書いておきます…。
(JSONのほうに書く方法がメジャー?)

なお、管理画面のスタイルでは box-sizing: border-box; の設定がないようです。
「記事をプレビューする分には問題ないけど、編集画面で段ずれが起きる!」などなどの場合は、こいつをブロック用のCSSに含めてやるとよさそう。

②:JSONを登録

テーマファイル内の blocks/charaspeech/ の中に、block.json を作成します。

{
  "name": "acf/charaspeech", //※1
  "title": "キャラトーク",
  "description": "うちのこの会話を表示します",
  "category": "dp-custom-blocks", //※2
  "icon": "format-chat",
  "keywords": ["会話, chat, うちのこ"],
  "acf": {
    "mode": "auto",
    "renderTemplate": "render.php"
  },
  "supports": { //※3
    "align": false,
    "anchor": true,
    "className": true
  },
  "example": { //※4
    "attributes": {
      "mode": "preview",
      "data": {
        "__is_preview": true
      }
    }
  }
}

※1:nameにはアンスコがつかえないっぽいのでご注意ください~
(自動出力スクリプトのIDなどで、アンスコはハイフンに変換されてるので、そのあたりの関係??)

※2:先ほど functions.php で作成した独自カテゴリに含めるようにします

※3:編集画面右に出てくる「高度な設定」で、もろもろサポートするかどうか?の設定。
いちおう、カスタムのID (anchor) とクラス (ClassName) は設定できるようにしました。

※4:example の項目は、編集画面のブロックリストでカーソルを当てた時に表示されるサンプル画像に関する設定だったと思います。いちおうサンプル画像 (thumb.png) も作ったので書いておきます。

③:ACF PRO でフィールドを登録

キャラ+吹き出し1つに対して1つのブロック…でもよいのですが、今回はPRO版の醍醐味「繰り返しフィールド」を使いました。

フィールド全体の設定

ロケーションルールブロック・等しい・キャラトーク

繰り返しフィールド

全般 > フィールドタイプ繰り返し
全般 > フィールドラベルキャラ会話
全般 > フィールド名cb_cspeech
全般 > レイアウトテーブル ※

※:テーブルが一番、高さを取らずコンパクトな表示だったので…

繰り返しサブフィールド①

全般 > フィールドタイプ選択
全般 > フィールドラベルキャラクター
全般 > フィールド名cb_cspeech_chara
全般 > 選択肢 ※haruka : ハルカ
kai : カイ
全般 > 戻り値の形式 ※両方 (配列)
検証 > 必須項目有効

※:キャラの画像ファイル名・キャラ名の処理を両方行いたかったので、どちらも取得できるように設定

繰り返しサブフィールド②

全般 > フィールドタイプテキストエリア
全般 > フィールドラベルセリフ
全般 > フィールド名cb_cspeech_speech
検証 > 必須項目有効
プレゼンテーション > 改行自動的に <br> を追加 ※

※:管理画面で入れた改行が、そのまま表で反映されるように設定

④:render.php、CSS で表示設定

テーマファイル内の blocks/charaspeech/ の中に、render.php を作成します。

<?php
//※1
if (!empty($block['data']['__is_preview'])) {
  echo '<img src="' . get_template_directory_uri() . '/blocks/charaspeech/thumb.png" alt="">';
  return;
}

//※2
$anchor = '';
if (! empty($block['anchor'])) {
  $anchor = 'id="' . esc_attr($block['anchor']) . '" ';
}

//※2
$class_name = 'cb_charaspeech__wrapper';
if (! empty($block['className'])) {
  $class_name .= ' ' . $block['className'];
}
?>
<div <?= $anchor; ?>class="<?= $class_name; ?>">
  <?php
  if (have_rows('cb_cspeech')) { //※3
    while (have_rows('cb_cspeech')) {
      the_row();
      $chara = get_sub_field('cb_cspeech_chara');
      $img = '/img/blog/chara/' . $chara['value'] . '.webp'; 
      $name = explode('_', $chara['label'], 2); //※4
  ?>
      <div class="dp_customblock cb_charaspeech__box">
        <div class="chara">
          <img src="<?= $img ?>" alt="<?= $name[0] ?>" title="<?= $name[0] ?>" width="100" height="100" loading="lazy">
        </div>
        <div class="speech">
          <?php echo get_sub_field('cb_cspeech_speech'); ?>
        </div>
      </div>
  <?php
    }
  } ?>
</div>

※1:先ほどの json で、サンプル画像の設定があったら、サムネイル画像を適用する…というもの

※2:先ほどの json で、サポートを有効化した ID (anchor) とクラス (ClassName) に関する設定。記事の編集画面の「高度な設定」から入力があった場合は反映できるようにします。

※3:ここから繰り返しフィールドのループ処理。投稿のループ内ではないですが、IDの指定は不要のようです。(というか、そもそも何のIDを入れるかもわからないですし…汗)
今回、キャラもセリフも必須設定にしたので、「値があったら~~」のような処理は入れていません。

※4:今後キャラアイコンのバリエーションを増やす場合は、ACFでラベルにアンスコを入れて設定するようにしました。ラベルの1番目のアンスコの前が名前として表示されます。

例)haruka_2 : ハルカ_らぶらぶモード とすると、表示時のキャラ名は変わらず「ハルカ」となる

あとはCSSで整えてあげればOK!
(このサイトの場合、SCSS で記述後に CSSに変換しています)

:root {
  --std-atclMgn_btm: 1.25em;
  --cb-text-main: #2c3338;
  --cb-bg-main: #fff;
}
.dp_customblock > * {
  box-sizing: border-box;
}

.cb_charaspeech__wrapper {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  margin: calc(var(--std-atclMgn_btm) * 2) 0;
}
.cb_charaspeech__box {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
  gap: 16px;
  & .chara {
    width: 80px;
    & img {
      aspect-ratio: 1 / 1;
      object-fit: cover;
      width: 100%;
      height: auto;
    }
  }
  & .speech {
    width: calc(100% - 96px);
    background: var(--cb-bg-main);
    color: var(--cb-text-main);
    line-height: 1.6;
    padding: 16px;
    border-radius: 8px;
    position: relative;
    &::after {
      content: "";
      width: 0;
      height: 0;
      border-style: solid;
      border-width: 10px 20px 10px 0;
      border-color: transparent var(--cb-bg-main) transparent transparent;
      display: block;
      position: absolute;
      left: -12px;
      top: 30px;
      z-index: -1;
    }
  }
}

@media all and (min-width: 641px) {
  .cb_charaspeech__box {
    gap: 24px;
    & .chara {
      width: 100px;
    }
    & .speech {
      width: calc(100% - 124px);
      padding: 20px;
      &::after {
        left: -16px;
        top: 40px;
      }
    }
  }
}

完成!

これで完成です🎉

ちなみに、ディレクトリ構造はこんな感じです。

カスタムブロック「キャラトーク」のディレクトリ構造

具体的なソースとともに紹介しましたが…
「自分もうちのこをブログ上でしゃべらせたい!!」
という方、その他カスタムブロックを作ってみたい方のお役に立てば幸いです。

ハルカ
あのね!
学園の入り口近くにクレープのキッチンカーが…!
カイ
まじ?
無茶ぶりメニューせびりに行こうぜwww
ハルカ
あう
【Figma】テキスト全体にグラデーション枠線を適用するメモ

本職デザイナーではないのですが、Figmaにはかなりお世話になっています。
最近公開した素材の解説画像も、Figmaで作っていたりします。

(それまではクリスタで作っていたのですが…Figmaは余白サイズがすぐわかったり、オートレイアウトしてくれたり、コンポーネント化できたり…ちょっとした画像調整もできるし、超便利✨)

とはいえ、手当たり次第で使っているので (のうすじ)、実は基礎的なところがわかっていなかったりします。

これまでハマって実現できなかったこと

いままでハマっていたのが、「複数行のテキストの枠線 (境界線) に対して、全体にナナメの線形グラデーションをかける方法」がわからないということ。検索の仕方が悪いのか、調べてもなかなか目当ての方法が出てきません。

↑理想

2行のテキストをグループ化、グループに対してグラデーションを適用した場合、水平方向 (各行個別) であれば実現できるのですが…

今回は「テキスト2行全体で」ナナメグラデーションをかけたいのです。
(クリスタだと、フォルダにまとめて → フォルダに対して「境界効果」を設定すれば全体に適用できるので、そのノリだったのですが…)

しかも、グループに対してのグラデーションでは「グラデーションを回転」ができないらしく…
テキスト要素それぞれを選択することで、ようやく「グラデーションを回転」が効く仕様のようで…。
(回転できるのも 水平方向 or 垂直方向 のみなので、今回の要件を満たさず)

いろいろ試してみるものの…

試行①:2行のテキストをグループ化、それぞれラスタライズ、全体のグループに対してグラデーションを適用

試行②:↑の各行ごとのグループを解除して同階層にしたうえで、全体のグループに対してグラデーションを適用

いずれもNG。

解決!

しばし考え…本日思いついた解決法がこちら。

テキストを複製して、下のほうにだけ目的の線幅で枠線を追加 (色は何でもOK)

2つのテキストグループの間に、目的のグラデーションを適用した長方形を追加
(長方形のグラデーションであれば、好きな角度に調整可能!)

下の方のテキストと長方形を選択し、「マスクとして使用」

できました!🙌

この方法、テキストをアウトライン化しなくてもできるので、あとでテキストを修正したくなった時も楽ちんです。(上下2レイヤー分修正しないとですが…)

さっそく活用

さて、やっと方法がわかったので、さっそくつかってみます!

かわいいね!!

なんでつくったかというと、本サイトのHOME最下部のバナーリストに加えるためです。
(メインのブログではなく、日々のらくがきなどはTWEETコーナーにポイポイしていることが多いため…)

かわいいね!!!!

応用として、上のテキストだけ若干ずらすと、本記事のサムネイル画像のような感じにもできます👍

かわいいね!!!!!!!

まとめ

以上、手当たり次第にFigmaを攻略している (のうすじな) 人のメモでした。
Figmaを使い始めた方のお役に立ったら幸いです。


現在、仕事が絶賛繁忙期で…
こころが荒んだり、そもそも体力が残っていなかったりして、全然更新できていないのですが……

今後も自分の城をゆっくりしっかり発展させてゆきます…。

【WordPress】ACF PRO をつかってカスタムブロックを作成!

WordPressのカスタマイズは多少わかるけど、込み入ったこととなるとちょっと…

…な ほたか が、ACF PRO をつかってカスタムブロックをつくることができた!というお話です。

【2025/04/06 追記】
↑その2を書きました。実際のコードを参考にしたい方はこちらの方がよいかも。

(なんかモメてるらしいですが) みんなだいすき「Advanced Custom Fields」。
いつの間にか、このプラグインでカスタム投稿タイプ、カスタムタクソノミーまでつくれるようになってただけでも驚きだったのに、オプションページまで作れるようになってたとは… (いまさら

オプションページで繰り返しフィールドまで使えて、最強過ぎませんかね…
((ヒィヒィ言いながら functions.php にコード書いて設定ページ作ってた過去の自分ェ…

さらには、なにやらACFのフィールドを「ブロック」にも適用できるとな…!?
残念ながらPRO版のみらしいですが…神過ぎますね。

カスタムブロックといえば…。

ブロックエディタでURL単体をぺろっ貼り付けると、勝手に「埋め込み」が適用されるのですが…
たいていの場合

「このコンテンツを埋め込めませんでした。」
余計なことをしておいて、「結局ダメでした!」。

…そんなモヤモヤを、カスタムブロックをつくることで (ついに) 解決できる!

しかしひとつ懸念が。

聞いた話では、カスタムブロックをつくるには React.js とかがつかえないとダメとかなんとか…?

そんな事になると学習コストがすごそうなので考えてしまうかもですが、
ダメ元で調べていたら、どうやらそんなことをしなくても良さそう!?

▼ 読んで勇気づけられた記事

ただ、コチラの例では入力周りも含めて自分で設定するタイプだったので、少しばかり内容が異なるようで… (よくわからずに進めたのもあり、メチャクチャはまってしまった)

結局は公式の記事をみながら進めました。(公式の推奨する「JSONに記載する方法」)

このサイトは完全オリジナルのテーマをつかっているので (子テーマの対応の必要なし)、その点がまた異なりましたが…💦

試行錯誤の結果…こんなものが出来上がりました!

「外部リンクかどうか (真/偽)」のフィールドをつくり、外部リンクの時だけ「target=”_blank” をつける」「別窓で開く旨を示すアイコンを表示する」設定をしています。

これで、Wordpressに埋め込みを拒否られたとき・Wordpress標準の埋め込みリンクが気に入らないときにも、イイかんじにリンクを設置できます。やったー!🙌

ACF PRO をつかえば、ポンコツほたかでもカスタムブロックをつくることができました!

よくわからないけど、カスタムブロックをつくりたい…なひとの、わずかな勇気につながりますように…

ハマりポイント

今回ハマって時間がかかってしまったポイントも書いておきます…
前提として「仕組みとか色々とよくわからないままやった」ので、くわしくわかっていらっしゃる方々にとっては「当たり前やん」な事かもですが…笑

acf-json フォルダをつくる

しれっと書いてて見逃してました笑
が、大事なものらしいです。ACF側でフィールドを設定→保存したところ、その設定データのファイルが自動出力され格納されていました。

日本語版Wordpressの公式 にある記述を使用するとうまくいかなかった

"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"render": "file:./render.php",

↑この辺を追記したりしたら失敗しました…
ACFの使用を前提とした場合は、WP公式が提示しているやり方とも若干変わるっぽいです。

記号の使い方

"name": "acf/testimonial",

name には、必ず「acf/」などと「名前空間」の指定をしなければならない…とのことですが、コレを入れるとうごかなくなり、消すと動き出す…という現象にしばらく悩まされました。

結論からすると「acf/」のあとの方が問題でした。
ここにアンスコをつかうと良くないっぽいです。
(WordPressの自動出力スクリプトなどでは、アンスコではなくすべてハイフンがつかわれているので、その関係?)

エディタなんかでは、アンスコをつかった方が、ダブルクリックで一気に選択出来ていいんですけどね…
結局はどちらの記号もつかわない名称で登録、解決しました。

追記

実装出来て、一呼吸着いたので、ファイル名などをもっと自分で管理しやすいように変更してみたり…

その中で、CSSをJSON内で読み込むと、「今回作ったブロックをつかっていなくても」「ヘッダー内に直書き出力される」ことがわかりました。CSSの内容は大したことないので、ページのパフォーマンス的にはそこまで気にするほどではないですが…ヘッダーは極力すっきりさせたいです。

というわけで、JSONの方のCSS設定を削除し、

  "name": "acf/richlink",
  "title": "カスタムリッチリンク",
  "description": "サムネイル画像、テキスト等を手動設定できます",
  "style": ["file:./style.css"], // ← これを削除

functions.php のほうに、「このブロックの使用があるときのみ」読み込むようにします

add_action(
  'init',
  function () {
    wp_enqueue_block_style(
      'acf/richlink',
      array(
        'handle' => 'acf-richlink-style',
        'src' => get_theme_file_uri('/blocks/richlink/style.css'),
        //'path' => get_theme_file_path('/blocks/richlink/style.css')
      )
    );
  }
);

“src” と “path”、両方入れると相変わらずヘッダー内に直書きで出てしまうので、結局 “path” の方は消しました。

…が、あれ…このブロックをつかっていない記事でも読み込まれてる……??

まあ、直書きで出ることは無くなったので、いったんそれで良しとして、後日調べてみますかね…💧

↑こういうコードハイライターとか、いろいろプラグインを入れている以上しかたないのですが、極力ヘッダーはキレイにしたいもの…。

さらに追記 (2025/04/06)

このブロックをつかっていない記事でも読み込まれてる……??

サイト全体が「ブロックテーマ」で作られていないと、「ブロックを使用しているときのみ読込み」はできないっぽいです…。(このサイトは、記事以外にはブロックを使わない「クラシックテーマ」タイプなので、どのページでも読み込まれてしまう模様)

また、別件。
CSSを当てると、ブログ記事のプレビューでは問題ないけど、編集画面でレイアウト崩れが起きる!
…という場合。

.my-custom-block,
.my-custom-block > * {
  box-sizing: border-box;
}

こいつを入れて解決するかもしれません。

まぁ、表に出るものではないので、気にしなくてよいといえばよいかもですが…。

城の手入れ

Date :
Category : Web制作
城の手入れ

とつぜんコード書いたりしらべたりしたい欲が出てきたので…
とてもとても久々に、城 (という名の自分のサイト) の手入れをしました。

コードの見直し

非推奨になっていた関数やら、昔未熟だったころに書いた非効率なコードを書きなおしました。
外観的にはほとんど変わりは無いですが…

CSSを SASS → 1行CSS に変更したり、JavaScriptを統廃合したり…
多少はパフォーマンス向上してるといいな…

とりあえず、自分の成長が実感できて良かったです。

セキュリティ対策対策

WordPressの自動出力スクリプトがいくつもあって、うざいナーとおもいながら確認していたら…

「oEmbed (JSON)」「oEmbed (XML)」の中身をなんとなく見てみたところ、なんと「見えたらよろしくないデータ」までバッチリ出ていたではありませんか…!

やばいやばいと至急対応。

手っ取り早いのは、このoEmbedの自動出力を無効化することだと思いますが…
万が一だれかがうちの記事を埋め込もうとした場合に不格好なことになったらやだナー…という不安から、無効にしていませんでした…

とりあえず、気づいてよかった。

SEO対策アップデート

記事ページを中心に、「構造化タグ」なるものを追加してみました。
個人サイトレベルで、どこまで効果があるものなのかはわかりませんが…
とりあえず、少し経ったらまた様子をみてみます。

Googleも推奨している「JSON-LD」形式を採用。

ただ、一部のコンテンツタイプ (「WebSite」など) は Search Console で認識してくれないらしく…
エラーチェックなどする場合は、Search Console ではなく「Schema.org」の検証ツールをつかった方が良さそうです。

パンくずリストの構造化タグは、使用しているプラグイン「Breadcrumb NavXT」のほうで出力してくれます。(bcn_display_json_ld() 関数で実装)

ただ、プラグインのデフォルトテンプレートが「RDFa」形式に対応したものだったので (だいぶ前からつかっているから?)、構造化タグ情報が2つ入っている状態…
なおした方が良いのかな💦

Home「WebSite」「SiteNavigationElement」「ItemList」
※Homeには新着情報集みたいな役目もあるので、いちおうアイテムリストも追加…SEO的にどうなのかは不明
アーカイブページ「BreadcrumbList」「ItemList」
※アーカイブページ特化のものは無いっぽいので、「ItemList」にしてみました…
投稿詳細ページ「BreadcrumbList」「BlogPosting」

SNSシェアボタンアップデート

「Twitter」のままだったり「G+」があったり、最近は色々SNSが増えてきたので…
ひとまず、「TWEET」の記事のシェアボタンをアップデートしました。
たぶん、TWEETに投稿後、じぶんで押すのがメインになると思います(笑

BlueskyもMisskeyも、ちゃんと公式からロゴデータやシェア用URLを用意していてくれてよかったです。

(SNS増えすぎィ…すべては奴のせい)

また何か気づいたらちょくちょく直していきます。

つぶやきコーナーをつくってみました

転職してワタワタしているうちに、ついに1年ほど更新しないでしまいました…

いえね、外部サービス各所では、描きかけのものなどを上げてみたりしていましたが…
最近「ブログ」をちゃんと書こうとすると億劫になってしまって、良くないですね…

…とか、

その「外部サービス各所」をめぐってみて、やはり結論が「自分のサイトでやればよくね?」的な事になったりして、

いっそのこと、このサイトに「ブログLITE版」「つ●ったーとく●っぷその他諸々の良いとこ取り」「画像も音楽も動画も載せたい」…といった ほたか仕様の機能をつけてしまえ!

…ということで、土日つかって開発しました。

https://diceproj.com/tweet/

・かざらないテキスト・画像・動画・音楽 複数同時投稿可能
・メディア欄にも反映
・版権・年齢制限とかのクッション対策はしてない
 (そういうのを載せるつもりはない)
・タグ機能
・ついーとボタン (ついでにURLコピー機能)
・OGP設定しっかり
・ついでに既存ページのプログラム修正

ついったーでもできないことを実装した!偉業!!

ただでさえ遅筆なところ、2~3話分同時に進めているもので、さらに更新が心許ない…

ので、ここで進捗をポイポイしていこうかしらと…

ところで、現在の知識で新しいページをつくったら…

このサイト全体もリニューアルしたくなってきましたね…

ぐぬぬ