line-height が思ったとおりにならないので検証してみた

## ことの始まり

最近、フロントエンドを勉強し直しているのですが、インライン要素は`line-height`で縦方向の中央揃えができる、という話を聞きました。

https://codesandbox.io/embed/gifted-silence-78lkym?fontsize=14&hidenavigation=1&theme=dark

お手軽で便利ですね。
<br>
<br>
<br>
ところがこれ、画像と並べただけで割と簡単にこわれます。

https://codesandbox.io/embed/line-height2-4tjnyc?fontsize=14&hidenavigation=1&theme=dark

<br>
<br>
<br>
理由が気になったので色々と調べてみたところ、

どうも**高さが不揃いの要素が並ぶ**とうまく機能しないようです。

https://codesandbox.io/embed/line-height3-8g3yyx?fontsize=14&hidenavigation=1&theme=dark


これは、インライン要素の`baseline`という概念が関係しています。
<br>
<br>
<br>
## baseline とは

端的に説明すると、文字列の下端を貫く線です。  
アルファベットの`g`や`y`のようにはみ出す無作法者もいますが、基本的に文字は`baseline`を基準に整列しています。

![baseline.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72316/6d604b39-c379-3c98-b2ad-9c29cf7b2734.png)

インライン要素が複数並ぶとき、一本のbaselineが用意され、それに沿って要素が配置されます。  
これが重要です。
![baseline2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72316/5319e3b4-d75e-57ba-b504-c7319d824a1c.png)


意外にも画像はブロック要素ではなくインライン要素であり、`baseline`があります。  
`baseline`は下端と一致しています。

![baseline3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72316/62af12d9-baa6-886d-b5c9-674580b012e2.png)


これが画像と並んだときに、文字が中央揃えされない理由でした。


## vertical-align というプロパティ

ところで、インライン要素には`vertical-align`というプロパティがあり`baseline`がデフォルト値になっていますが、`text-top`、`text-bottom`、`middle`などを指定することも可能です。

https://developer.mozilla.org/ja/docs/Web/CSS/vertical-align


試してみましょう。

https://codesandbox.io/embed/line-height4-xs3t6l?fontsize=14&hidenavigation=1&theme=dark

これはなに？？？
この現象がこの記事を書こうと思ったきっかけでした。
更に調査してみましょう。
ブラウザが壊れてしまったかのような表示ですが、一つ一つ検証してひもといてみましょう。


## text-top と text-bottom
MDN によると、`text-top`および`text-bottom`は以下のような定義になっています。
<dl>
    <dt>text-top</dt>
    <dd>要素の上端を親要素のフォントの上端に揃えます。</dd>
    <dt>text-bottom</dt>
    <dd>要素の下端を親要素のフォントの下端に揃えます。</dd>
</dl>

順に見ていきましょう。

まず、`line-height: 100px`を指定された文字があります。
![baseline4 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72316/83c3bc3c-8e72-0fee-651c-9e30310122ec.png)

これの横に`text-top`を指定された文字を並べます。
![baseline5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72316/bb12643f-cfcb-6b24-e1d5-71d6242b57ec.png)
**要素**の上端を**フォント**の上端に揃えるので、緑色の円で示したラインが接続されます。
<br>
<br>
<br>
さらに`text-bottom`を指定された文字を並べます。
![baseline6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72316/31a0ecff-e37d-79e5-6473-e03751ab71c5.png)
**要素**の下端を**フォント**の下端に揃えるので、緑色の円で示したラインが接続されます。
<br>
<br>
<br>
さあ、完成しました。これが`line-height`を指定された`text-top`と`text-bottom`の配置です。
![baseline7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72316/78b33d05-e664-aa7d-9336-227d9ed50ad0.png)


## top と bottom と middle
MDNには以下のようにあります。

<dl>
    <dt>top</dt>
    <dd>要素と子孫要素の上端を行全体の上端に揃えます。</dd>
    <dt>bottom</dt>
    <dd>要素と子孫要素の下端を行全体の下端に揃えます。</dd>
    <dt>middle</dt>
    <dd>要素の中央を親要素の baseline + x-height の半分 に揃えます。</dd>
</dl>

一気に配置しましょう。こういうことです。

![baseline8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72316/c2f44998-f77b-b548-5ec6-981fa9445c60.png)
- `top`は要素の上端を揃えるので、上の赤線を接続。
- `bottom`は要素の下端を揃えるので下の赤線を接続。
- `middle`は`baseline`を基準に要素の中心を揃えるので緑線を接続。
（矢印部分が`x-height`の半分にあたります）

これが完成形です。いかがでしょうか？
最後にもう一度、実際の配置を見てみましょう。

https://codesandbox.io/embed/line-height4-xs3t6l?fontsize=14&hidenavigation=1&theme=dark

実際には、`line-height`と`行全体の上下端`は別なのですが、通常はほぼ近似するため、今回は同一のものとして説明させていただきました。
（よく見ると、`text-bottom`と`top`が少しずれて並んでいますよね）

## 蛇足

`line-height`と`行全体の上下端`が別であると考えるきっかけとなったサンプルです。

https://codesandbox.io/embed/loving-benji-t7vjqm?fontsize=14&hidenavigation=1&theme=dark

- `line-height`が水色の領域
- `フォントの上下端`は見た目通り文字の上下端
- そして、（おそらく）`行全体の上下端`が`top`と`bottom`の配置から推測できます。

`line-height`を大きくしても、`行全体の上下端`が一緒に広がるわけではないということですね。
<br>
<br>
あれこれと表示をいじった末の推測ですので、間違いがあったら教えてください。