はじめまして、先日microCMSにカスタマーエンジニアとして入社した下津曲です。
Webメディアの記事や採用コンテンツにおいて、以下のような、左右から吹き出しで人が話しているように見えるデザインにしたい場合があるかと思います。
実際に、microCMSの導入をご検討されているお客様からも、このような見せ方はできるのか?といったご相談をいただくことがしばしばあります。
例えば、以下はWebメディア「新R25」の例です。
今回はWeb制作におけるTipsとして、microCMSの繰り返しフィールドを使って上記のようなデザインを作るのに便利なAPIスキーマを構築してみようと思います。
APIを作成し、スキーマを定義する
今回は、簡単のためにサービスは作成済みと仮定して進めていきます。
API名は「対談コンテンツ」、エンドポイントはinterview
としました。なお、APIの型はリスト形式です。
早速APIスキーマを定義していきます。
まずは対談コンテンツのタイトルを以下のように定義しました。ひとまずこの状態で「作成」をし、対談の中身はのちに繰り返しフィールドを使って定義します。
次に、メインの対談部分のスキーマを作ります。
基本的な考え方として、以下のように「本文(normalText
)」と「対談文(talkText
)」をそれぞれカスタムフィールドとして作成し、繰り返しフィールドを用いてそれらを繰り返し入稿できるようにします。
- 本文(
normalText
):地の文を表現する - 対談文(
talkText
):話者の名前と画像、話す内容を表現する。話者の位置を左と右で出し分けられるようにする。
本文のカスタムフィールドを作成する
まずは、本文(normalText
)のカスタムフィールドを作成します。
スキーマとしてはシンプルで、リッチエディタのみを持つようにします。
レイアウトもそのまま1カラムにしておきます。
対談文のカスタムフィールドを作成する
次に対談文(talkText
)のカスタムフィールドを作成します。本文と同様に基本情報を入力し、次のステップへ。
スキーマは以下のようにしてみました。
ポイントとしては、isLeft
という真偽値を定義している点です。isLeft
がtrue
の場合は左から、false
の場合は右から吹き出しが現れるようなイメージです。
また、レイアウトは2カラムにしました。
カスタムフィールドの作成はこれで以上です。
繰り返しフィールドとして、元のスキーマに組み込む
次は、元のインタビューAPIに、これらを繰り返しフィールドとして組み込んでいきます。title
はすでに登録しているので、ここにbody
として対談本文用のフィールドを追加します。body
の種別には繰り返しフィールドを選択し、そのなかでさきほど作成した「本文(normalText
)」と「対談文(talkText
)」を追加します。
これでスキーマの準備は完了です!
コンテンツを入稿する
作成したAPIにコンテンツを追加していきましょう。
例として、以下のような流れを作ってみました。(序盤以降は省略しています)
この段階でAPIプレビューをしてみると、以下のように値が返却されます。fieldId
には、normalText
ないしtalkText
が入っており、本文か会話文かが判別できるようになっています。
{
"id": "qhmc5cwnl",
"createdAt": "2023-01-12T03:10:46.426Z",
"updatedAt": "2023-01-16T08:47:16.262Z",
"publishedAt": "2023-01-12T03:10:46.426Z",
"revisedAt": "2023-01-16T08:47:16.262Z",
"title": "対談コンテンツのテスト",
"body": [
{
"fieldId": "normalText",
"text": "<p>左の人と右の人がいるようです、なにやら会話をしていますね。</p>"
},
{
"fieldId": "talkText",
"name": "左の人",
"image": {
"url": "https://images.microcms-assets.io/assets/49ce787cbf474c57b26125e4b29ce467/713b1c30939b4b96a4fc978fac998562/icon_com_reverse.jpg",
"height": 1000,
"width": 1000
},
"text": "<p>どうも、はじめまして左の人です。</p>",
"isLeft": true
},
{
"fieldId": "talkText",
"name": "右の人",
"image": {
"url": "https://images.microcms-assets.io/assets/49ce787cbf474c57b26125e4b29ce467/e5795c4f862b44788edac4c4e4bab410/icon_com.jpg",
"height": 2200,
"width": 2200
},
"text": "<p>やあ、私が右の人です。</p>",
"isLeft": false
}
]
}
繰り返しフィールドに設定したAPIから返ってくる値については、「繰り返しフィールド・カスタムフィールドをマスターしよう」の記事に詳しく書かれているので、詳細はそちらをご参照ください。
コードを書いてスタイリングする
入稿データができたので、あとはAPIからデータを取得して、表示していきます。
APIからデータを取得して表示するまでの流れは本件の本題とずれてしまうので、そちらの詳細については「microCMS + Next.jsでJamstackブログを作ってみよう」や「microCMS + NuxtでJamstackブログを作ってみよう」の記事を参考にしてみてください。
スタイリングし、最終的に以下のような見た目になりました!
いかがでしょうか、いわゆる対談風の見た目になっているのではないでしょうか。
方法としては、とてもシンプルで、各talkText
の出し分けをする際、isLeft
がfalse
の場合において、スタイルを変更しています。
<main className={styles.main}>
<h1 className={styles.title}>{taidan.title}</h1>
{taidan.body &&
taidan.body.map((elm: any, idx: number) => (
<div key={idx}>
{elm.fieldId === 'normalText' ? (
<div className={styles.normalText} dangerouslySetInnerHTML={{ __html: `${elm.text}` }}></div>
) : elm.fieldId === 'talkText' ? (
// ここで左の吹き出しか、右の吹き出しかを出し分けている
<div className={clsx(styles.talkText, !elm.isLeft && styles.reverse)}>
<div className={styles.person}>
<Image src={elm.image.url} alt={''} width={60} height={60}></Image>
<div>{elm.name}</div>
</div>
<div className={styles.body} dangerouslySetInnerHTML={{ __html: `${elm.text}` }}></div>
</div>
) : null}
</div>
))}
</main>
該当部分のCSSは以下の通りです。
.normalText {
margin-bottom: 32px;
font-size: 16px;
}
.talkText {
margin-bottom: 32px;
display: flex;
align-items: flex-start;
}
.talkText.reverse {
flex-direction: row-reverse;
}
.talkText.reverse > .person {
margin-right: 0;
margin-left: 20px;
}
.body {
padding: 20px;
width: 100%;
border: 1px solid #ddd;
border-radius: 4px;
}
.person {
display: flex;
flex-direction: column;
align-items: center;
margin-right: 20px;
}
.person > img {
border-radius: 50%;
}
.person > div {
margin-top: 8px;
font-size: 14px;
font-weight: bold;
}
おわりに
今回は、Webメディアの記事や採用コンテンツにおいて結構需要の多い対談風デザインの設計と実装についてご紹介しました。
このケースですと、話者の名前や画像は毎回入力する形になっていますが、この部分はコンテンツ参照機能を使うなどのアップデートをすることで、より効率的に入稿することもできそうです。
その他、繰り返しフィールドを活用することで、柔軟なコンテンツ表現が可能になりますので、ぜひいろいろチャレンジしてみてください!