Webテキストを理解したい

## 導入

![button.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612989/ea2d0efb-39ef-7482-c21c-5488d002185e.png)

ボタンですね。  
  
何の変哲もないです。
だいたいこんな感じ⬇️で実装すると思います。
```Scss:CSS
.button {
  display: inline-grid;
  place-items: center;
  border-radius: 9999px;
  width: min(30vw, 400px);
  min-height: 44px;
  background-color: darkcyan;
  font-family: "Noto Sans JP", sans-serif;
  color: white;
}
```

place-itemsで中央寄せしてるし、
テキストには色しか指定してないのに
なんか上の余白の方が広いですね。。  

`line-height: 1` を指定してみても結果は同じです。

なんでなんでしょうか


:::note info
この記事は英語のフォントを基準にした話が多くなっています。
日本語フォントについては違う箇所もあると思うのでご了承ください。
:::

## font-sizeって何なん

Webテキストにはそれぞれ **emスクエア**（UPM / units per emとも呼ばれる）
という相対的なサイズの「ボックス」があるみたいです。  
（もともとは金属活字において大文字「M」のプロポーションが  
正方形になるように作られた基準みたいです。）  

一般的にOpenTypeフォントでは1000単位、  
TrueTypeフォントでは2のべき乗 1024, 2048など~に設定されます。  


`font-size` の指定でこのボックスの基準値を変更することで、  
表示されるテキストのサイズを変えることができます。

:::note info
日本語フォントは『全角』という言葉もあるように、
一般的にこのemスクエアに収まるように設計されているようです。
:::

### Webテキストにある5つのラインについて
またWebテキストには、
フォントごとに設定された5つのラインがあります。

![5lines.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612989/b9bd59a7-839d-0f89-9a98-0e555e4a02e3.jpeg)
（[出典]Google Fonts -Exploring x-height & the em square: [https://fonts.google.com/knowledge/choosing_type/exploring_x_height_the_em_square](https://fonts.google.com/knowledge/choosing_type/exploring_x_height_the_em_square)）

- **アセンダ**（Ascender）　エックスハイトより上に突き出る文字の部分。b, l など
- **ディセンダ**（Descender）　ベースラインより下に突き出る文字の部分。p, j など
- **エックスハイト**（x-height)　小文字xの上部から下部まで。
- **ベースライン**（Base line）　エックスハイトの下部のライン。
- **キャップハイト**(Capotal Height)　大文字の上部からベースラインまで。

> ボックス（emスクエア）の境界は通常、
キャップハイトの少し上、ディセンダの少し下に位置する
>
by Google Fonts

このラインをもとにemスクエア内にフォントが配置されますが、
上下のラインまでの距離がフォントごとに違うので
謎に上が空いていたりするんですね。。。

### x-heightについて
欧文書体には大文字に対する小文字の高さ（x-height）」の比率の基準があります。  

フォントごとに大文字に対しての小文字のアスペクト値が違うので  
フォールバックフォントでサイズ感が変わってしまう😇ということが起きるんですね…

### フォントの仮想空間を見てみる
![text-test_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612989/c0693709-7079-b4da-381c-047198453781.png)

画像は同じフォントサイズの  
__Noto Sans JP__ と __ヒラギノ 角ゴ Pro__ を  
背景色だけをつけた ```<span>``` に入れた状態です。

何だこれは、、  
全然違うじゃん、、  

フォントによってこれだけx-heightにも差が出るなら  
フォールバックフォントは極力使用したくなくなりますね…

フォントによって設定されている基準が違うから余白ができたりするんですね

![button_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612989/baac7f55-219a-004b-dcd8-7ca5c8c0ea27.png)

さっきのボタンのフォントを上下の空間の差が少ない __ヒラギノ 角ゴ Pro__ に変えたら
真ん中に見えるようになりました。

### x-heightをCSSで操作
ちなみに…
x-heightによって決まる
フォントのアスペクト値は `font-size-adjust` プロパティを使用して一定にすることもできます。  

:::note warn
※Firefox, Safariでのみ使用可能です。2023.12.02現在
Can I Use: https://caniuse.com/?search=font-size-adjust
:::

## line-heightって何なん

最初の疑問は解決しましたが。。
ついでなので ``line-height`` についても調べました。  

Webに限らず、『読む』という本来の目的を考えれば
line-heightとテキストはもはやマナカナくらいニコイチの関係です。


### webのline-heightの設定方法

Webでは。。
line-heightにfont-sizeより大きい値を設定すると
テキストコンテンツの上下にスペースが追加され、「１行の高さ」となります。

![text-test_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612989/f6a6b5e3-220a-31fa-c2ca-f005ed9d2aa9.png)

このスペースは **leading（レディング/リーディング）** と呼ばれ、
上下に半分ずつ追加されるので **half-leading（ハーフレディング）** とも言います。

### 行間とアクセシビリティ

ちなみに…
WCAGでは、達成基準の1つとして以下のように推奨されています


> 段落中の行送りは、少なくとも 1.5 文字分ある。そして、段落の間隔は、その行送りの少なくとも 1.5 倍以上ある
> 達成基準 1.4.8 視覚的提示 (https://waic.jp/translations/WCAG21/#visual-presentation)

アクセシビリティ的には
本文のline-heightは1.5欲しいということですね

### 行送りと行間

もともと、印刷の世界において、
レディングはテキストの **ベースライン間の距離** で設定されていました。
この段落の距離のつけ方を『行送り』といいます。

なぜWebのレディングを印刷のそれに合わせなかったのかは、
Webにおけるテキストボックスの役割の多さ、
背景やボーダーをつけた時のことを考えれば必然。。。

デザインとWebのレディングの差はここから始まったんですね…

## デザインツールのleadingの取り扱い

- Photoshop, Illustrator
  - 従来の「行送り」の方法で設定されます。（ベースライン間の距離）
  > 行送りについて
  > テキスト行のベースラインから、その上の行のベースラインまでの距離を示します。
  - ※ アジア言語は仮想ボディ基準で行送りされます
- XD
  - line-heightと同じようにハーフレディングで行間がつきます
  - 最終行にはつかないです
  - ※ 文字オブジェクトの高さが実際の行の高さと異なります
- Figma
  - line-heightと同じようにハーフレディングで行間がつきます
  - Figmaの行間は厳密にはCSSと違い2行目以降は上にレディングが追加されるので2行目以降のテキストとの余白は調整が必要みたいです。
  - 詳しくはFigmaの line-heightについての記事⬇️ に書いてあります。

https://www.figma.com/ja/blog/line-height-changes/


## テキストの余白を綺麗に実装する

なるべくデザインデータに合わせるためにはどのように実装したらいいでしょうか

### ネガティブマージンなどで調整
```Scss:CSS
.text {
  margin-top: -0.2em;
}
```

ネガティブマージンなどで細かく調整する方法です。
ただフォントが変わると逆にずれてしまったりするので注意が必要です。

### 疑似要素で余白をつめる
![flex_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612989/52671943-d65d-4c50-8dc2-037f72ce0bb1.png)

1行目の行間のせいで上が揃わない…
みたいな時は疑似要素で無理やり行間を詰めることで
テキストの行間は保ったまま上下を詰めることができます。

```Scss:CSS
/* mixin */
@mixin lineHeightCrop($line-height: 1.5) {
  &::before {
    content: "";
    display: block;
    margin-top: calc((1 - #{$line-height}) * 0.5em);
    width: 0;
    height: 0;
  }
  &::after {
    content: "";
    display: block;
    margin-bottom: calc((1 - #{$line-height}) * 0.5em);
    width: 0;
    height: 0;
  }
}

.heading {
  /* ... */
  line-height: 1.4;

  @include lineHeightCrop(1.4);
}

```

![flex_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612989/2a54d367-e97f-d126-74a7-7274371644f5.png)

### text-box-trim / text-box-edge

\:loudspeaker: まだ草案段階のプロパティです。
  ``text-box-trim`` はもともとは ``leading-trim`` で提案されてました。

![text trim](https://github.com/jantimon/text-box-trim-examples/raw/main/docs/intro.webp)
text-box-trim / text-box-edge プロパティを使用することで
テキストの余分な余白を消すことができるみたいです！
ボタンのテキスト中央寄せが簡単になる時代が来るかもしれないですね。。！

https://triple-underscore.github.io/css-inline-ja.html#leading-trim

https://triple-underscore.github.io/css-inline-ja.html#text-edges

:::note warn
※現在Safari Technology Preview でのみ使用可能です。2023.12.02
Can I Use: https://caniuse.com/css-text-box-trim
:::

## まとめ

Webのテキストを理解してより綺麗なタイポグラフィを目指していきたいです \:sparkles:

### 参考記事
最後に参考にした記事を載せます。見ていただいてありがとうございました🙇🏻‍♂️
- [Deep dive CSS: font metrics, line-height and vertical-align](https://iamvdo.me/en/blog/css-font-metrics-line-height-and-vertical-align)
- [Exploring x-height & the em square](https://fonts.google.com/knowledge/choosing_type/exploring_x_height_the_em_square)
- [Google Fonts Em](https://fonts.google.com/knowledge/glossary/em)
- [FontForge The EM Square](http://designwithfontforge.com/en-US/The_EM_Square.html)
- [ほとんどの人にはどうでもいい行間の話](https://workabroad.jp/posts/2287)
- [文字を思い通りの大きさと位置で表示するCSS](https://coliss.com/articles/build-websites/operation/work/font-size-is-useless.html)
- [フォントのサイズ設定は役に立たない、問題点と解決方法](https://coliss.com/articles/build-websites/operation/work/font-size-is-useless.html)
- [line-heightの不要な上下の余白を打ち消して、デザインデータに沿ったコーディングを効率化する方法](https://yuyakinoshita.com/blog/2020/01/20/line-height-crop/)