スライダーのダイナミックブロックを作ってみた話

サイト制作でよく依頼のある「スライダーの設置」を、カスタムブロック(ダイナミックブロック)でサクッと実装できるようにしたくて、あれこれ試行錯誤した話です。

この記事は、ブロック入れたらそれだけでスライダーが実装できるようになる!という話とは、違いますので、そういうものをお求めの方は、即離脱をお勧めします。

なお、当方、黒い画面とかReactとか、そもそもJavascriptが大の苦手だということも初めに宣言しておきますね・・・。

トップページにスライダー欲しいって話

ウェブサイトの制作で、トップページのファーストビュー内にビジュアルスライダーが欲しい、という話がよくあります。

ウェブサイトをWordPressで作るなら、サイトを形作る要素のおおよそは管理画面で操作できたほうがいい、と考えています。その範囲は多ければ多いほど良い。それゆえ、スライダーを作る場合も、管理画面で、できればクライアントで自由に管理できるほうがいいかなと。

スライダーの要件

今回の話の前提は「サイトにひとつだけ、トップページにスライダーを設置する」というものです。私にくる依頼の大半はこれなので。
その上で、下記のような要件を想定しています。

  • スライドはクライアントで自由に管理したい
  • スライドの枚数に制限を設けない(0〜多数)
  • スライドの並べ替えを可能にしたい
  • スライドの内容を保ったまま表示/非表示を切り替えたい
  • 日時を指定してスライドの公開をしたい

スライドの中身は、画像だけやHTMLコンテンツを入力するものなど雑多なものがあると考えています。この要件を満たす方法を考えます。

閑話休題:そもそも・・・要る??

スライダーについてはかなりカジュアルに依頼はくるものの、いつも思うのは「それ必要?ユーザのためになる??」です。あくまで個人の意見ですが。
オートプレイになっているスライダーをゆっくり眺めるようなユーザいるのかしら?、バナーやCTAコンテンツのカルーセルとしても、せいぜい1枚目で離脱では?…などなど、思うところは多々あります。動きのあるものはアクセシビリティを担保しようとするとだいぶ手間もかかります。
それをおしてまで、設置する意義とは?ということをつい考えてしまいます。

なので、私の中でスライダーはあまり工数をかけたくないUIという位置付けです。

これまでのスライダー実装

これまでは以下の方法で作ることが多かったです。

  1. 'wp_enqueue_scripts' フックをテーマの functions.php に記載してスライダー用ライブラリを読み込み
  2. 上記は、必要なページでのみ読み込まれるように、条件分岐を書く
  3. スライダーのコンテンツはカスタム投稿を作って、1スライド1記事で管理
  4. フロントへの出力はテンプレートパーツで記載
  5. 上記のテンプレートパーツを呼び出すショートコードを作り、ブロックエディタもしくはテーマエディタに配置

Swiper というライブラリが気に入っていてよく使っています。このライブラリで必須のJavascriptとCSSのファイルをテーマフォルダに入れています。トップページのみでスライダを使う前提なので、スライダを不要とするページでファイルが読み込まれないように条件分岐を書いています。

スライダーのコンテンツをカスタム投稿を作って管理するのは、要件にある「並べ替え」「表示/非表示の切り替え」「日時指定で公開」あたりを実現するのに都合が良いからです。

もちろん、他にもやり方はあると思いますし、案件によって異なると思います。

並べ替えもWordPressのデフォルトである「日付の降順」と説明して、日付の操作で管理してもらうことがあります。もしくはサクッとGUIで記事を並べ替えできるプラグインを使います。
並び順の情報なのだから、日付ではなく、専用のメタ情報を使うべきだろうと思います。実際、日時投稿と組み合わせる場合は「日付の降順」だけでは対応できないこともあるでしょう。
WordPress はもともと記事に「順序」というデータを付与できます。固定ページにありますね。カスタム投稿を追加する時に、サポートする機能のところで「ページ属性('page-attributes')」を追加すれば使うことができます。管理画面でも「順序の昇順」に従って記事が並ぶようにするには、ひと手間かける必要があります。また、順序は列にも表示されないので、わかりやすくするなら、こちらもひと手間かけて表示するのが良いかと。こう書くと、結構面倒ですね。

スライドの中身、記事の管理画面については、必要な入力内容をカスタムフィールドであらかじめ決めておくことが多いです。

カスタムフィールドを使うのは、そのほうが入力しやすいと感じるクライアントがいるためです。ブロックにも慣れて欲しいな、と思いますが、人を変えるのは難しいので・・・。
とはいえ、例に挙げたのは画像とかリンクだけのシンプルなものでそれほど手間でもないですが、自由な内容にしたいと言われるとカスタムフィールドを用意するのが面倒な場合も。

余談:カスタムフィールドについて

カスタムフィールド、つまり投稿メタをつかう場合の基本的なポリシーは、情報設計に則しているか、寄与するものに限定する、です。メタデータって必要なものは必要だと思っています。なんでもかんでもWYSIWYGエディタに塊のHTMLで突っ込んでしまって良しとは思えないので。たとえば、イベント情報のようなものなら、イベントの内容自体はWYSIWYGエディタに自由に書けばいいけど、開催日や開催場所の情報など、独自に取り出せるように適切なデータ型でメタ情報に取り分けておく。そうしないとそのデータを使って絞り込みや串刺し検索がしずらいな、と考えます。

一方で、入力しやすくするためとか、見た目を整えるためだけにメタデータを作るのは、違うよなと思っています。コンテンツの中で2カラムを作りたいから1カラム目2カラム目をそれぞれカスタムフィールドに入れて、という感じのものです。こういうのが、ブロックで対応できるようになって、マジ神。

カスタムフィールドを使う場合は、もうほとんど、Advanced Custom Fields (ACF) プラグイン頼りになっています。とはいえ、プラグイン依存も脱却したいなとは思っています。カスタムフィールドに値を保存する用のブロックを作ることが、今後の課題です。

余談が長くなりましたが、本来、スライダーの中身の部分は、カスタムフィールドで作るべきものとはちょっと違うだろうなと思っています。

カスタムブロックにするメリットとは?

まあ、正直なところ、そんなに多くないかなとは思っています。そもそもの動機はカスタムブロックの勉強がてらだったわけで。違いといえば、以下のようなことでしょうか。

  • ブロックが挿入されたページだけでスライダに必要なライブラリを読み込むことができるので、テーマの functions.php にいちいち記述をしなくていい
  • プラグインに独立できるので使い回しがもう少し容易になる(微々たるものかも)

プラグインにしたとしても、フロント側は、毎回案件ごとちょっとした変更を加える必要があるかもなので、単純な使い回しにはできないですけどね。今までのやり方よりは、多少、現代的?な、やり方になるような気が・・・します!(強引)

ブロックのプラグインを作成

先ほどのスライダーの要件に加えて、スライダーのブロックの要件を補足しますが、ブロックを挿入しても、管理画面では「ここにスライダが表示されます」というテキストが表示されるだけのものを想定しています。ダイナミックブロックで、レンダリングはフロントだけです。className が追加できるだけの、ごくごくシンプルなもの。いままでもショートコードだったので、そこは、諦めの境地ということで。

プラグインの雛形は、「create-block」パッケージを使って作りました。これがないと、カスタムブロックが作れない。開発してくれた人ありがとう・・・!

ビルド後ですが、ファイル群はこんな感じ。

scrフォルダどこ行ったよ?ですが、ええ、やっちゃダメなんでしょうけど、buildフォルダの中身を直接書き換えています。言い訳をすると、いちいちビルドするやり方がどうにも慣れなくて・・・。

良い子は真似しちゃダメだよ!

ライブラリの読み込みはPHPで

生成されたプラグインのPHPファイルに、wp_register_script関数とwp_register_style関数で、ライブラリのファイルを登録。

これにたどり着くまで一悶着あって(というかたどり着いた後も大変だったが)、Twitterで、できないできないと騒いでいたら、アドバイスをいただきました。

まじ神。

「普通にview.jsでimportできたらそれが一番簡単」というのは、納得で、Swiper もnpmインストール対応のライブラリではあるんです。
が、残念ながら、私があんまりよくわからんので、慣れた方法でスクリプトを読み込みたかった。

こう言ってしまうと元も子もないのだけど、node 使って、ビルドして、というやり方に本当慣れなくてですね・・・。プラグインのPHPファイルに書いて、実際のファイルを読み込んで、ライブラリの必須ファイルもプラグインに留めておけば、もしも差し替えたかったら、FTPなりで差し替えればいいなーと思って。ビルド必要ないじゃん。

良い子は真似しちゃダメだよ!!!

不勉強で、そもそもビルドなしの方法でダイナミックブロック作れないことを解決すべきなんだけど、これも今後の課題ですねー。

ちなみに、wp_register_script関数とwp_register_style関数で、読み込むファイルのURL(パス?)を記述するところ。下記の記述では、ローカルの環境ではパスの解決がうまくいかなくて、ファイルを読み込めなかった。

plugins_url( 'swiper/swiper-bundle.min.js', __FILE__ )

wp-now で作ってた環境だったから??
解決方法もわからずこちらも棚上げになっています。誰か教えて欲しい・・・。

block.json は、だいたいこんなもので。

スライダーの発火用とか細かい設定用のJSは view.js に書いて、スライダーの見た目に必要なCSSはstyle-index.cssに書けば良い。

フロントにレンダリングする内容は、render.php に書くのだけど、おおよそこんなもので。

ひとまず、カスタムブロック側はこんな感じで用意しました。

スライドの登録方法について

スライド用のカスタム投稿を準備して、1スライド1記事でスライドの中身を登録します。以前は記事管理画面にカスタムフィールドを用意して入力してもらうようにしていました。

スライドの中身は、ほとんどの場合画像だけですが、画像がPC用とスマホ用と別だったり、画像だけではなくコンテンツスライダーにする場合なども、たまにある。
また、カスタムフィールドにするべき情報とも捉えていないし、なるべく脱却したい。

一番自由にするなら、記事のブロックエディタにスライドの内容を任意に入力してもらうことだが、入力枠があらかじめ用意されていないと入力しづらい人はいる。これをどう解決するか?

例えば、あらかじめ雛形になるブロックが入っていて、任意の画像やテキストに差し替えるだけなら、かなりハードルは下がるのかな?と考えました。

そしてそれを実現する方法・・・・・ありました!

ブロックテンプレートを利用する

正確な日本語訳がわからないですが、ブロックテンプレートといって、新規記事を作ったときに所定のブロックを配置しておく方法があるようです。詳しくは下記に。

実際には、こんなふうに書いてみました。書いた場所はプラグインのPHPファイルです。

そうすると、管理画面では、こう。

わざわざ画像を指定して読み込んでいますが、こう、ダミー画像を用意して、そこにある程度説明を書いておけば、便利かな、というだけなので、ただの画像で良い場合は下記のような記載で十分と思います。

$post_type_object->template = array(
	array( 'core/image', 
		array(
			'sizeSlug' => 'full',
		)
	),
);

各ブロックに設定する内容のキー名は、実際に一度、ブロックエディタ内で組んでみた上で、コードエディタモードで、各ブロックの波括弧内をみるといいかなと思います。

あとは、Attributes の内容はコードに表れないものもあるので、下記のコアブロックリファレンスを参考にしました。

まとめてあるの助かるけど、本当の一次情報としたら、下記を見て、ブロックごとの block.json に何が書かれているか?を調べることになるのかな。

https://github.com/WordPress/gutenberg/tree/trunk/packages/block-library/src

まあたいへん。

別案:ブロックパターンを選択

スライドの記事を新規追加する時に、「パターンを選択」のモーダルを表示して、任意の雛形を選択する方法もあるかなと思うので、一応紹介です。コンテンツスライドの入力パターンが複数あるなら、こちらの方法が良いかも。

「パターンを選択」のモーダルは、表示したいパターンの登録時に、メタデータを次のように書いておくと、出てきます。

Block Types: core/post-content
Post Types: slider

Block Types に 「core/post-content」が書かれていることが必須のようです。さらに、今回はスライダーでしか使わないため、Post Types にスライダの投稿タイプを指定しています。設定しないと、全ての投稿タイプで表示されてしまうのではないかな・・・?

というか、これだけでモーダル実装できちゃうのかと思うとすごいなあ、と。
よくよく調べたら、下記の記事が見つかった。6.0から実装されてたんですね、知らなかった・・・。

2024テーマで実際に使われているのを見たとき、最初は、記事の新規追加するたびにモーダルが表示されてウザいなあ、と思ったけど。雛形を入れておくことで入力を助けるというのがユーザのサポートになる場面は、意外とあるのかな、と考え直しました。浅慮を反省。

余談 ブロックパターンについて

パターンの登録方法

テーマへのパターンの登録方法は2種類ある。

  1. テーマに /patterns フォルダを作って、そこへphpファイルでパターンの内容を記述する
  2. register_block_pattern() 関数で記述する

最初の方法は、ブロックに対応したクラシックテーマでも使えたので、こちらの方法のがいいと思う。下記に詳しく。

ファイルヘッダー Template Types について

パターンのPHPファイルの最初に記述するファイルヘッダーのキーの中で、「Template Types」についての補足を。

ブロックテーマの場合、管理画面からもテンプレートが増やせるのだけど、テンプレートを新規追加する時にも、「パターンを選択」モーダルが出ます。そのモーダルに出したいパターンに、「Template Types」を設定すると良いみたい。下記は2024テーマの例。

公式の記事は、おそらくこちら。

コアパターンの拒否方法

パターンがあまりに多くなっても、しんどいので、テーマで実装したもの以外は隠したい場合、fonctions.php'after_setup_theme' のアクションフックで、以下を記述。

remove_theme_support( 'core-block-patterns' );

おわりに

というわけで、なんかとりあえずスライダーのダイナミックブロックができました。テーマに書くのと手間の面ではそれほど変わらないかもしれないなと思いつつ。ベストな方法ってきっと人それぞれでしょうから。

コメントをどうぞ

メールアドレスが公開されることはありません。 が付いている欄は必須項目です