チャットみたいに、吹き出し風に会話を表示したいなぁー。
もちろんアイコンを設定できて、左右どっちに置くかも指定したいよねぇー。
難しいプログラムのコードは触らないでできたらいいなぁー。
任せて!そんなトフトフのために、チャット風画面を作るカスタムブロック作っちゃおう
わーい!
トークとか、インタビューとか、FAQのページが良い感じに表示できるね☆
こんにちは!エンジニアの jun です。
茶番にお付き合い頂きありがとうございます。
というわけでは、チャット風のカスタムブロックをご紹介。
自由に画像を設定可能で、画像の左右レイアウトを任意に指定することが出来きます。
インタビューやFAQなどのコンテンツと相性が良いと思います。
下記のリンクからファイルをダウンロードしインポートすれば、お使いのブログで利用可能です。
ダウンロードしてね!
カスタムブロック
それでは早速カスタムブロックの詳細を見ていきましょう。
ブロックの作成
まずはブロックの設定から。
今回は「画像」、「画像の配置」、「メッセージ」の3つを設けました。
入力欄 | 利用するブロック | 補足 |
画像 | 画像 | チャットの画像。正方形推奨。正方形以外は、画像の一部が切り取られる。 |
画像の配置 | ドロップダウン | 画像の左右を選択。 |
メッセージ | テキストボックス | チャットのメッセージ。 |
ポイントとしては、ドロップダウンをオプションとして利用している点でしょうか。選択した内容は実際には表示されず、CSSのクラスとして利用しています。
詳細のついては以下をご覧ください。手前味噌で恐縮です。
【カスタムブロック】ドロップダウンを使って、スタイルをカスタマイズできるリンクボタンをつくろう
カスタムスクリプト
続けてカスタムスクリプト。
大まかに3つの工程に分かれます。
- ライブラリを読み込む。
- テンプレートになるHTMLを記述。テンプレートエンジンに mustache.js を利用。
- メインの処理を記述。入力された画像などをテンプレートに受け渡す。
// ライブラリを読み込み
<script src="https://cdn.jsdelivr.net/npm/mustache@4.2.0/mustache.min.js"></script>
// テンプレートになるHTMLを記述
<script type="x-tmpl-mustache" id="chat-item-template">
<div class="chat-item img-position:{{img-position}}">
<div class="chat-item-head">
<figure>
<img src="{{img.src}}" alt="{{img.alt}}" width="100" height="100" loading="lazy">
<figcaption>{{img.caption}}</figcaption>
</figure>
</div>
<div class="chat-item-body">
{{{message}}}
</div>
</div>
</script>
// メインの処理を記述
<script>
document.addEventListener('DOMContentLoaded', async () => {
if ( document.body.dataset.hasCompiledHtml ) return
const $img = document.querySelector('.img img')
const data = {
img: {
src: $img.src,
alt: $img.alt,
width: $img.width,
height: $img.height,
caption: document.querySelector('.img figcaption')?.textContent || '',
},
'img-position': '右' === document.querySelector('.img-position')?.textContent ? 'right' : 'left',
message: document.querySelector('.message')?.innerHTML || '',
}
const template = document.querySelector('#chat-item-template').innerHTML
const rendered = Mustache.render(template, data)
MTBlockEditorSetCompiledHtml(rendered)
});
</script>
HTML構造とメインの処理を切り分ける目的で、 mustache.js というテンプレートエンジンライブラリを利用しています。
もしHTMLを改変したい場合は、この箇所を編集してください。
Logic-less {{mustache}} templates with JavaScript
また、画像の「代替テキスト」と「キャプション」もそのまま出力しています。
「キャプション」は、チャットの人物名として利用しています。もちろん、空のままでも大丈夫です。
スタイル
最後にスタイルを記述します。
ただ、スタイルに必須の要素はないので、お好きな見栄えに自由に編集してみてください。今回は、あくまで一例として、このようなデザインで作りました。
<style>
.chat-item{
--bg-body: #dcf7f5;
--flex-direction: row;
display: flex;
gap: 2rem;
flex-direction: var(--flex-direction, row);
align-items:flex-start;
}
.chat-item.img-position\:right{
--flex-direction: row-reverse;
--bg-body: #f7f7f7;
}
.chat-item + .chat-item{
margin-top: 1rem;
}
:not(.chat-item) + .chat-item{
margin-top: 3rem;
}
.chat-item-head{
flex: 0 0 100px;
}
.chat-item-head figure{
margin: 0;
}
.chat-item-head figcaption{
text-align: center
}
.chat-item-head figcaption:empty{
display: none;
}
.chat-item-head img{
border-radius: 100%;
aspect-ratio: 1/1;
object-fit: cover;
}
.chat-item-body{
position: relative;
flex: 1 1 auto;
padding: 1rem;
border-radius: 8px;
background: var(--bg-body, #dcf7f5);
}
.chat-item-body::before{
content: '';
position: absolute;
top: 16px;
left: -15px;
width: 0px;
height: 0px;
border-top: 15px solid var(--bg-body);
border-right: 0px none;
border-left: 15px solid transparent;
}
.chat-item.img-position\:right .chat-item-body::before{
left: auto;
right: -15px;
transform: scaleX(-1);
}
.chat-item-body :first-child{
margin-top: 0;
}
.chat-item-body :last-child{
margin-bottom: 0;
}
</style>
なお、サンプルのJSONを読み込んだだけでは、チャットのスタイルが適用されるのは管理画面のみです。
そのため、実際の表示側にもスタイルを適用する必要があります。方法は様々ですが、一例として、上記の <style>
タグを丸ごと <head>
タグへ記載するとスタイルが利用出来ると思います。
完成!
うれしー。これが欲しかったのー!
さっそく試してみよっ!
ありがとう!ぜひ活用してね!
これからもいろんなカスタムブロックを紹介するから、お楽しみに〜!