ちょっとわかりにくいタイトルになってしまいましたが、つまり Wikipedia のやつ (Fig 1) みたいに、「画像 (またはビデオなどの埋め込みコンテンツ) の下にキャプションをレイアウトするとき、キャプションが複数行にわたる場合は画像の幅に合わせて折り返したい (ただし画像の幅はバラバラ)」というのをシンプルかつ汎用的なかたちで実現する CSS を考えてみました。というか、このブログのレイアウト用にけっこう長いことあれこれ考えてたもののこれといった手が思いつかなくて放置していたんですが、上手い解決を Stack Overflow でみつけた のでパクった、という話です。
<figure>
<img src="/img/photo.jpg">
<figcaption>Lorem ipsum dolor sit amet</figcaption>
</figure>
ここではこのマークアップをもとに考えてみます。スタイルの要件をまとめると以下のとおり:
figure
の幅はimg
の幅に合わせたいimg
の幅は不確定figcaption
は存在しない場合もあり、もし存在すればテキスト量は不確定で、幅はfigure
の幅に合わせ、複数行にわたる場合はなりゆきで折り返したい
考えられるアプローチのひとつとして、figure
の幅についてあらかじめいくつかのパターンを決めておくというものがあります。img
は figure
の幅に合わせて書き出してもいいし、大きめに作っておいてブラウザで縮めてもいいでしょう。シンプルなグリッドがきっちり決まってる場合なんかはいいかもしれませんが、マークアップの class
属性や data-*
属性などを指定する必要があり、あまり汎用的とは言えないかもしれません。
figure.small { width: 160px; }
figure.mideium { width: 240px; }
figure.large { width: 320px; }
figure img { max-width: 100%; }
あるいは JavaScript で img
の幅を取得して figure
の幅を操作するという手もあります。これならかなり汎用性も高いです。ただ、JavaScript で画像のサイズの取得をエラー処理やなんかも含めてきっちりやるのって、けっこうたいへんですよね? 僕は何度か挫折しました…
あとは CMS とかのシステム側でうまいことやってもらうって感じですかね。画像のアップロード時に、その幅に応じて style
属性を自動的にかますような。Wikipedia なんかはそんな感じ でしょうし、WordPress のプラグインなんかでもそんなのありそう (調べてない)。
というわけで、やはり CSS だけでなんとかしたいなーというのが以下のコード。前述の Stack Overflow で見つけたやつに少しアレンジを加えたものです:
figure {
display: table;
width: 160px; /* minimum width */
*width: auto; /* for IE7 and below */
}
これだけ。figure
はテーブルのように振る舞うので、img
の幅が figure
に指定した幅を超えた場合はその幅に合わせて広がります。またもし img
の幅が figure
に指定した幅に満たない場合でもつねにその幅が確保されます。figcaption
は横に広がろうとしますが、figure
の制限をうけてぴったりの幅に収まります。ちなみにここでは figure
と figcaption
ですが、div
と span
やなんかでも同じです。デモを用意したのでどうぞ:
Stack Overflow のバージョンだと width
の値が 1px
なんですが、それだと img
の幅がごく小さいときに figcaption
がせまくなり過ぎて読みづらいので、サイトのグリッド構成などに応じて最低限これだけの幅はほしいという値を指定しておくのがいいと思います。ちなみにその場合、img
は左に寄せず中央に置くと座りがいいです。
同じく Stack Overflow バージョンは img
と figcaption
に対して display: table-row
を指定していますが、それは必要ない気がします。検証した限りとくに不都合はないのでたぶん大丈夫だと思うんですが…
また、もし img
に max-width: 100%
というスタイルが指定されていると figure
の幅に縮められてしまうので注意が必要です。レスポンシヴなデザインでよく使われるスタイルだと思いますが。
display: table
をサポートしていない IE7 以下では figure
の幅が width
の値のとおりに解釈され、結果として縦にひしゃげたかたちになりキャプションが読みづらくなってしまうので、width: auto
で上書きしています。とは言えこれで IE8 以上と同じレイアウトになるわけではなく、ただボックスが横に広がるだけです。IE7 では figure
と img
に max-width
を指定すればある程度はコントロールできます (Fig 3) が、もし同じレイアウトでということになると、前述のような JavaScript を用いたり幅を固定したりといった手法が必要でしょう。
Web コンテンツがスマートフォンやタブレットといった多様なデバイスで閲覧される機会が増え、canvas や SVG といった手法も広まってきたいま、「画像」をいかに取り扱うかというのはあらためて考えなければいけない課題のひとつです。今回ここで紹介したのはレイアウトに関するちょっとしたテクニックに過ぎないですが、将来に向けてできる限りシンプルで汎用性の高い手法を模索していきたい、と考えた結果でもあります。
あけましておめでとうございます!