inline layoutを使いこなす 第1回 画像の余白 1
vertical-align: topの指定で、画像の余白はなぜ消えるのでしょう? 要素がどのようにレイアウトされていくのかinline layoutの仕様を理解すると、なぜそうなるのかがきちんと説明できるようになります。
はじめに
本シリーズでは、なんとなく使っているけれど、実はあまりよく知らないという人も多いであろうinline layoutについて解説します。
このシリーズで言うinline layoutとは、簡単に言うと、行やdisplayプロパティがinline
やinline-block
である要素、またそれに隣接するテキストなど、block box内に配置されるコンテンツが、どのようにレイアウトされ、ブラウザに表示されるかを示した仕様のことを指します。Web上で参照できるW3Cの仕様としては、以下に概ねまとめられています。
- CSS Inline Layout Module Level 3
- CSS3 module: line
- Visual formatting model
- Visual formatting model details
筆者は、コーディング中に生じた疑問を調べていったら、上記仕様群を読み込むに至りました。始まりは疑問だったのです。そこでこの記事は筆者が疑問に感じた事象をベースに話を進めていきたいと思います。
なお、紹介するサンプルは次のリポジトリからダウンロード、またはクローンできます。併せて参照してください。
inline layoutサンプルリポジトリ
vertical-align: topで消える余白
コーディングをしていると、次のように画像を配置することがあります。
画像間に20px
の余白を空けたい。なのでこのようにHTMLとCSSを書いたとします。
<div class="photoBlock"><img src="photo.jpg" alt=""></div>
<div class="photoBlock"><img src="photo.jpg" alt=""></div>
<div class="photoBlock"><img src="photo.jpg" alt=""></div>
.photoBlock {
margin: 0 0 20px;
}
一見問題なさそうに見えますが、このとき.photoBlock
に背景色を付けてみると、次のように表示されます。
画像の下に余白ができています。これだと実際には20px
以上空いているように見えてしまいますから、この余白部分を消したいです。そこでimg
にvertical-align: top
を当ててやります。
.photoBlock img {
vertical-align: top;
}
すると、画像直下の余白は消えます。
ちなみにbottom
、middle
を指定したときも消えます。めでたし。
……なのですが、なぜこのようになるのでしょうか。経験的に使っていた指定ですが、筆者はきちんと理解していなかったので、調べてみることにしました。
このvertical-align
の挙動を理解するには、行がどのようにレイアウトされるのかを理解しなければなりません。まずfont-size
とline-height
の関係から理解していきましょう。
font-sizeとline-heightの関係
次のようなHTMLとCSSがあるとします。
<p><span>The quick brown fox jumps over the lazy dog....</span></p>
p {
font-size: 16px;
line-height: 16px;
background: #a6dbbe; /* green */
}
span {
background: #f197f1; /* purple */
}
すると次のような表示となります。
このとき、文字の大きさは16px
で、行の高さも16px
です。行ごとに四角で囲むと、次のようになります。
font-size
もline-height
も16px
なので、文字の大きさも行の高さも16px
という状態です。
line-heightを広げた場合
では、このときline-height
をもっと広げたらどうなるでしょうか。今度はfont-size
は16px
のままですが、line-height
を24px
としました。
p {
font-size: 16px;
line-height: 24px;
background: #a6dbbe; /* green */
}
このときは、次のような表示になります。
さて、文字の大きさと行の高さについて、詳しく見ていきましょう。
このときピンクの間に見える背景のグリーンの部分が、line-height
を指定することで広げられた「行間」となりますが、この部分のことをleadingと言います。
そして、このleadingは次のように、真ん中で半分に分割されます。このように半分に分割されたleadingをhalf-leadingと呼びます。
1行というのはfont-size
分の高さを持った基本領域(inline box)の上下にhalf-leading分のスペースが加わり、成り立っています。このとき、1行の高さはline-height
が示す値、この場合で言うと24px
です。この値から基本領域の高さ16px
を引いた8px
がleadingの高さとなり、half-leadingの高さは4px
となります。
行の高さというのは、このようにfont-size
とline-height
から計算され、決定されています。
inline boxに関わる名称
レイアウトの仕組みをもっと突っ込んで見ていきましょう。各部の名称とともに見ていきます。概要を図にまとめました。
テキストやdisplay
がinline
やinline-block
である要素が配置される場合、まず始めに、それを配置するための箱が最低でもひとつ用意されると考えます。この箱のことをinline boxと呼びます。
紫で色を付けた領域です。テキストが配置される場合、このinline boxの高さが、1em
分の高さです。
例えばfont-size: 16px
と指定したら、このinline boxの高さが16px
となり、16px
が1em
として扱われるようになるという具合です。
そして、その上下にhalf-leading分の余白が加わり、1行の高さとなります。この高さがline-height
が示す高さとなります。こうして拡張されたinline boxのことを、extended inline boxと呼びます。line-height
が24px
なら、extended inline boxの高さが24px
となります。
このinline boxの上端をtext-before-edge、下端をtext-after-edge。extended inline boxの上端をbefore-edge、下端をafter-edgeと呼びます。
土台となるbaseline
inline layoutを考える上で重要なのが、baselineです。
baselineとは、その名が示す通り、文字の土台となるラインです。文字は通常、このbaselineを基準としてデザインされます。そして、ここから一定の距離のラインで、小文字の高さを揃えます。この高さがx-heightです(この高さは、CSS内で1ex
として利用できます)。
ちなみに、このbaselineはアルファベットを基準に考えた場合で、日本語などのbaselineは、これよりもちょっと下がbaseline(ideographical baseline)となります。
CSS3の仕様書を見ると、将来的には、このideographical baselineもvertical-align
などの基準位置として利用できるようになるようです。
行の高さの決まり方
先の例で見た通り、font-size
とline-height
により行の高さが決まるわけですが、1行の中に複数のinline boxが存在する場合は、それらがすべて収まるように、行の高さが決定されます。
この例では、b
、em
、i
の3つの要素が1行の中に収まっています。これらの要素を含む行の高さが、ほかの行に比べて高くなっていることに注目してください。
<p>The <b>quick</b> <em>brown</em> <i>fox</i> jumps over the lazy dog. ...</p>
p {
font-size: 12px;
line-height: 18px;
background: #a6dbbe; /* green */
width: 310px;
}
b {
font-size: 20px;
line-height: 30px;
background: white;
}
em {
font-size: 30px;
line-height: 40px;
background: orange;
}
i {
font-size: 40px;
line-height: 50px;
background: tomato;
}
このとき、1行目では各extended inline boxの配置がチェックされます。
この行では、<i>fox</i>
のextended inline box分の高さを確保すれば、すべてのextended inline boxが収まります。ですので、この要素に合わせた50px
の高さが、この行の高さとなります。
このようにしてブラウザは各行についてその行の高さを決定し、レイアウトを行います。
anonymous inline box
この例においてThe
とjumps ...
は、特にb、em、i要素では囲われていませんが、これらもinline boxを形成し、行の高さの計算に組み込まれます。このときのfont-size
とline-height
は親要素を継承するため、p
のfont-size: 12px
、line-height: 18px
が適用されます。このように明示的に要素で囲わずに形成されるinline boxをanonymous inline box(匿名インラインボックス)と呼びます。これを架空の要素の形にして考えると、次のようになります。
<p>
<anonymous>The </anonymous>
<b>quick</b>
<anonymous> </anonymous>
<em>brown</em>
<anonymous> </anonymous>
<i>fox</i>
<anonymous> jumps over the...
実は<b>quick</b>
と<em>brown</em>
と<i>fox</i>
の間にもスペースがあるため、ここでもanonymous inline boxが形成されています。
line box
ここまでで見てきたように、各行について、その行が内包するinline box群の高さが評価され、行の高さが決定されます。その行に収まらなかった内容は、次の行が作られ、その行に収められます。そして、その行でも収まらなかった場合はまた次の行へ……と、コンテンツがすべて配置されるまで行が作られ、積み上げられていきます。この「行」を表現する領域のことを、line boxと呼びます。
block box内にinline boxが存在する場合、1つ以上のline boxが用意され、その中にinline boxが配置されるといった具合です。例えば今挙げた例では、次のようにline boxが用意されています。
そして、その中に配置されるinline boxは、行をまたぐことができます。例えば、始めの<i>fox</i>
の次に配置されるjumps over the ...
のテキストを表現するanonymous inline boxは、次に登場する<b>quick</b>
に至るまで、行をまたいでずっと続いています。
block box内に配置されるテキストは、このようにline boxとinline boxの入れ子として計算され、レイアウトされています。
次回も引き続き、inline layoutについて見ていきましょう。