こんにちは。小学生向けのニュースサイト、こどもニュースをつくっています。
このサイトには縦書きの表示モードがあり、記事には画像が付きます。この 2 つを組み合わせたときに、いくつも問題が出ました。
最終的にたどり着いた形と、その理由を書きます。
問題 1: キャプションが横に伸びる
画像は <figure> に入れ、その中に <figcaption> を置いています。説明と出典を表示するためです。
縦書きの中でこれを組むと、キャプションが画像の左隣に縦一列で入ります。figcaption は figure のブロック方向に積まれるので、縦書きでは横方向になります。
figcaption は figure の block 方向に積まれるので、縦書きだと画像の左隣に縦一列で入る。
キャプションが画像の高さより長いと figure ごと縦に伸びて本文の高さを押し上げ、
折り返させても列が float の外(本文側)へはみ出して本文と重なる
キャプションが長いと、figure が縦に伸びて本文の高さを超えます。折り返させると、今度は横に広がって本文に重なります。
flex、grid、幅の指定を変えます。いくつか試しましたが、どれも解決しませんでした。
(figure の block サイズが width:61.8% で固定されているため、はみ出しを内側に収めるには
画像を縮めるしかなく、flex / grid / width:auto いずれも実測で解決しなかった)。
解決: figure だけ横書きに戻す
答えは、figure の中だけ書字方向を戻すことでした。
const HORIZONTAL_FIGURE_IN_VERTICAL = { writingMode: 'horizontal-tb' } as const;
これだけです。figure の中が横書きになるので、キャプションは画像の真下に入ります。長ければ通常どおり折り返し、figure の中に必ず収まります。
前例もありました。記事の見出しも、縦書きのときは横書きのままにしています。図版と見出しは、本文とは別の組み方をしてよい要素です。
副作用として、キャプションに含まれる英数字の横倒しも起きなくなりました。縦書きの中では英字が寝るので、出典に含まれるサービス名やライセンス表記が読みにくくなっていました。1 つの指定で 2 つ解決したことになります。
問題 2: スマホ幅で画像が列を占有する
もう 1 つ、スマートフォンの幅で別の問題が出ました。
縦書きの本文は、高さが固定で横スクロールするブロックです。ここに figure をそのまま流し込むと、横 1 画面ぶんの列を丸ごと占有します。
読んでいる途中に、画像だけの列が挟まります。しかも画面の端で見切れます。
一度は「画像を本文の外(下)に出す」ことも考えました。ただ、記事の内容と画像は対応しているので、本文中にあるほうがよいと判断しました。
解決: float を使う
縦組みでの float の挙動を利用しました。
const VERTICAL_INLINE_FIGURE = {
...HORIZONTAL_FIGURE_IN_VERTICAL,
float: 'right',
ml: 1.5,
} as const;
`float: right` は縦組みでは line-right = 段の下端を指すので、画像は列の下に貼り付き、
本文は同じ列の上側を流れて画像の左へ続く(縦組みの図版と同じ組み方)。
float: right は、横書きでは「右端に寄せる」ですが、縦書きでは「行の右側」=段の下端になります。
結果、画像は列の下に貼り付き、本文はその上を流れます。紙の縦組みで図版を入れるときの組み方と同じになりました。
float の向きが書字方向によって変わることを知らないと、この解決には行き着きません。CSS の論理的な指定(inline-start / block-start など)を意識していると、こういう挙動も理解しやすくなります。
幅は本文ブロックと同じ 1 画面ぶんに収めて、画像が画面をまたがないようにしています。
配置は 3 通り
最終的に、画像の配置は 3 通りになりました。
- 横書きで画面が広い: 本文の冒頭で右上に float
- 横書きでスマホ幅: 第 1 段落と第 2 段落の間に横いっぱい
- 縦書き: 段の下端に float(figure の中は横書き)
コンポーネントは 1 つで、配置の指定だけを差し替えています。
/** 記事画像 + キャプションの figure。配置(float / 段落間 / 本文の下)だけ sx で差し替える。 */
画像とキャプションの組み立ては同じなので、共通にしました。違うのは置き方だけです。
アスペクト比は変えない
どの配置でも、画像の縦横比は変えていません。幅を指定して高さを自動にする、または高さを指定して幅を自動にする、のどちらかです。
属性としても寸法を入れているので、読み込み前から場所が確保されます。読み込みでレイアウトが動きません。
配置を切り替えるときに、比率を変えたくなることがあります。ただ、写真の比率を変えると被写体が歪むので、そこは触らないと決めました。
まとめ
- 縦書きの中の
figcaptionは画像の横に入る。長いと figure が破綻する - figure だけ
writing-mode: horizontal-tbに戻すと、キャプションが下に入って収まる - 副次的に、キャプション内の英数字の横倒しも解決する
- 縦組みでの
float: rightは「段の下端」を指す。紙の図版と同じ組み方になる - 配置の違いは sx の差し替えで表現し、コンポーネントは 1 つにする
- どの配置でも縦横比は変えない。寸法は属性でも指定して場所を確保する