フォントの大きさが違う文字や画像を上揃えや下揃え、上下中心揃えにしたい時ってありますよね。
ぐぐると「inlineかinline-block要素でvertical-alignを使う」という記事は見つかるものの、実際にやってみるとうまくいかない。
vertical-alignは親要素と子要素のline-heightを揃える機能だよ
という根本的な理解ができていなかったために泥沼にハマったので参考までに記録しておきます。
親要素にline-heightを指定しろ
後でちゃんと解説しますが大事なのはline-heightです。
更に言うなら親要素にはfont-size:0を指定しましょう。
これでだいたい解決できます。
なぜ親要素にline-heightが必要なのか
親要素にline-heightがないと、font-sizeを基に暗黙のline-heightが設定されます。
vertical-alignは親要素と子要素のline-heightを揃える機能なので
親要素の暗黙のline-heightと子要素のline-heightが揃えられてしまいます。
親要素にheightと同じ高さのline-heightを設定しよう
ご想像どおりです。親要素のheightとline-heightを一致させればvertical-alignがほぼ正しく動作します。
「ほぼ正しく」と書いたのはvertical-align:middleはもうひと工夫必要だからです。これは後述します。
子要素にline-heightは必要ないのか
無くても通常は正しく動作しますが設定することを強く推奨します。
inlineとinline-blockにはheightが存在しません。
したがって要素の高さとline-heightは必ず一致します。
font-sizeが決まれば自動的にline-heightも決まるので何も指定しなくても良いわけです。
inlineとinline-blockの違いはfontの高さの外側の背景を指定できるか否かです。
ただ、親要素のheightよりも子要素のline-heightが大きくなると思ったように配置できない場合があるので親要素のheightを超えない様に子要素のfont-sizeとline-heightを指定しておくと良いです。
なお、font-sizeとline-heightは同じ高さにしておくと良いです。
親要素 ====
height:40px;line-height:40px;
子要素 ====
font-size:10px; line-height:10px;
または
font-size:10px; line-height:1; ← line-heightはfint-sizeの1倍
vertical-aligh:middleは大変
vertical-align:middleを指定すると縦の位置がほぼ中央揃えになります。
しかしよーく見ると子要素が少し下になります
原因は親要素と子要素の「縦の中心」の定義が違うからです。
その前にフォントの話。baselineを理解しておこう
フォントにはbaselineという考え方があります。
アルファベットのyの様にちょっと下に出るフォントのことを考慮して、少し下に余白があるのですが、この高さをbaselineといいます。
baselineの高さはフォントによって異なるため一定ではありません。
vertical-alignの縦位置は親要素と子要素で異なる
親要素のvertial-alignの縦位置の中心は、line-heightの中心にテキストを配置した際のbaselineです。
一方で子要素のvertical-alignの縦位置の中心はline-heightの中心です。
このため、親要素と子要素をvertical-align:middleで配置すると、子要素が少し下に表示されます。
(説明を忘れてましたが、vertical-alignはこ子要素にのみ指定できます。)
なぜこの様な定義にしたのか不明ですがそういう仕様です。
縦位置をぴったり揃えるなら親要素のfont-sizeを0にしよう
ご想像どおり、親要素のfont-sizeを0にすればbaselineもへったくれも無くなってちょうど真ん中に表示されます。
この場合、親要素の直下に記載された文字は表示されないので、必ずspan等子要素にして高さを指定しましょう。
ダメな例 ===
<div style="font-size:0;line-height:40px;height=40px;">
テキスト1 ←font-size:0なので表示されない
<span style="font-size:10px;line-height:10px";>テキスト2</span>
</div>
正しい例 ===
<div>
<span style="font-size:8px;line-height:8px";>テキスト1</span>
<span style="font-size:10px;line-height:10px";>テキスト2</span>
</div>