figure要素のマークアップについてのメモ

figure要素。

普通に書くとこんな感じ。

<figure>
  <figcaption>画像の説明テキスト</figcaption>
  <img src=".." alt=".."><img src=".." alt=".."><img src=".." alt="..">
</figure>

<figure>
  <img src=".." alt=".."><img src=".." alt=".."><img src=".." alt="..">
  <figcaption>画像の説明テキスト</figcaption>
</figure>
figure {
    margin: 1em 0;
}
figcaption {
    display: block;
    clear: both;
    font-weight: bold;
}
/* figcaptionが最初の場合 */
figcaption:first-child {
    margin-bottom: 0.5em;
}
/* figcaptionが最後の場合
 * img以外にもいろいろあるので全称セレクタ。
 * IE7を無視するなら figcaption:last-child {..}
 */
figure * + figcaption {
    margin-top: 0.5em;
}
/* --- img --- */
figure img {
    display: inline-block;
    *display: inline;
    *zoom: 1;
    margin-left 5px;
    vertical-align: top;
}
/* 一番左の画像 */
figure > img:first-child, /* figure内で最初の要素がimgの場合 */
figcaption + img /* figcaptionの次にくるのがimgの場合 */ {
    margin-left: 0;
    border: 1px solid #f00; /* 分かりやすいように赤枠をつける */
}
/* --- pre --- */
    :
/* --- object --- */
    :
/* --- video --- */
    :
/* --- canvas --- */
    :
/* --- svg --- */
    :

デモページをみる

スクリーンショット

問題点

うまくいってるように見えるけど、このままだとimg要素などがほかの要素でラップされているとダメだし、figcaption要素内にimg要素などがあった場合のスタイルをいちいち上書きする必要がある(めんどい)。

<figure>
  <figcaption>画像の説明テキスト<img src=".." alt=".."></figcaption>
  <a href="#"><img src=".." alt=".."></a>
  <a href="#"><img src=".." alt=".."></a>
  <a href="#"><img src=".." alt=".."></a>
</figure>

<figure>
  <a href="#"><img src=".." alt=".."></a>
  <a href="#"><img src=".." alt=".."></a>
  <a href="#"><img src=".." alt=".."></a>
  <figcaption>画像の説明テキスト<img src=".." alt=".."></figcaption>
</figure>
/* 一番左の画像 */
figure > img:first-child,
figure > *:first-child img, /* 追加。figure内で最初の要素の中のimg */
figcaption + img,
figcaption + * img /* 追加。figcaptionの次にくる要素の中のimg */ {
    margin-left: 0;
}
/* figcaption内の画像
 * セレクタを長くするか、!importantをつけないと詳細度で負ける。
 */
figcaption img {
    margin-left: 0 !important; /* override */
    border: 0 !important; /* override */
    vertical-align: middle; /* override */
}

デモページをみる

スクリーンショット

解決策

場合によってはキャプションとコンテンツを分けたほうがいいと思った。
ので、div.fig-contentを追加してみる。

<figure>
  <figcaption>画像の説明テキスト</figcaption>
  <div class="fig-content">
    <img src=".." alt=".."><img src=".." alt=".."><img src=".." alt="..">
  </div>
</figure>

<figure>
  <div class="fig-content">
    <img src=".." alt=".."><img src=".." alt=".."><img src=".." alt="..">
  </div>
  <figcaption>画像の説明テキスト</figcaption>
</figure>
figure {
    margin: 1em 0;
}
figcaption {
    display: block;
    clear: both;
    font-weight: bold;
}
/* figcaptionが最初の場合 */
figcaption:first-child {
    margin-bottom: 0.5em;
}
/* figcaptionが最後の場合
 * 全称セレクタやlast-childを使わなくてもOK。
 */
.fig-content + figcaption {
    margin-top: 0.5em;
}
/* --- img --- */
.fig-content img { /* figcaption内のimgには影響がない */
    display: inline-block;
    *display: inline;
    *zoom: 1;
    margin-left: 5px;
    vertical-align: top;
}
/* 一番左の画像 */
.fig-content > img:first-child, /* .fig-content内の最初の要素がimg */
.fig-content > :first-child img /* .fig-content内で最初の要素の中のimg */ {
    margin-left: 0;
	border: 1px solid #f00;
}
/* --- pre --- */
    :

デモページをみる

スクリーンショット

結論

figure要素内に何が入るのか、figcaption要素の位置や内容などが決まっている場合はdiv.fig-contentはなくてもいい。けど、入れておいた方が便利なことが多そうだと思った。