iOSでOSの文字サイズ設定を変更しても、ブラウザで文字の大きさが変わらない

iOSでは、設定の「画面表示とテキストサイズ」にある文字サイズ設定を変更したとき、iOSアプリで表示されている文字サイズを変更することができます。  
しかしブラウザで表示しているwebサイトの文字サイズは（多くの場合）変わりません。

iOSのアプリケーション開発の文脈では、この文字サイズ可変について「Dynamic Type」と呼んでおり、予め用意されているtext styleを選択することで有効になります。
https://developer.apple.com/documentation/uikit/uifont/scaling_fonts_automatically

iOSのブラウザ上で、このDynamic Typeを有効にするためには`font:-apple-system-body;` の指定が必要になります。

### font:-apple-system-bodyで何が起きるか
* 文字サイズが、OSの設定値で上書きされる
    * iOSでOSの設定がデフォルトの場合、16px > 17px
* 字体が-apple-systemと同様に変更される
    * 英数字はSF
    * 日本語はHiragino-sans
        * 日本語に1px程度の縮小処理

### -apple-system-bodyが指定できるプロパティ
`font`プロパティでは、`font-size`、`font-family`、`line-height`などをまとめて指定できるショートハンド指定の他に、`font:icon;` のようにキーワードを指定してシステムフォントの値でまとめて設定できる指定があります。
https://drafts.csswg.org/css-fonts-3/#font-prop

`-apple-system-body` はシステムフォントの値を指定するためにappleが独自に設定した値で、次のような値が用意されています。

https://developer.apple.com/library/archive/releasenotes/General/WhatsNewInSafari/Articles/Safari_7_0.html#//apple_ref/doc/uid/TP40014305-CH5-SW10

>-apple-system-headline
-apple-system-subheadline
-apple-system-short-headline
-apple-system-short-subheadline
-apple-system-body
-apple-system-short-body
-apple-system-tall-body
-apple-system-caption1
-apple-system-caption2
-apple-system-short-caption1
-apple-system-footnote
-apple-system-short-footnote

それぞれの値で`font-size`や`font-weight`、`font-style`などが異なります。

これらの値は`font-family`の他に`font-size`などの値も置き換えるためのキーワードです。そのためこのキーワードを`font-family`で直接指定することはできません。

<dl>
  <dt>NG:</dt>
  <dd><code>font-family: -apple-system-body;</code></dd>
  <dt>OK:</dt>
  <dd><code>font: -apple-system-body;</code></dd>
</dl>

### font-sizeへの影響
要素に `font:-apple-system-body;` を指定した場合、`font-size`が変更されます。OSの文字サイズ設定がデフォルトの場合、設定される値は次のとおりです。

||未指定|-apple-system-body|
|:-----------|------------:|:------------:|
| iOS(Safari、Chrome、Firefox)  | 16px | 17px |
| macOS(Safariのみ) | 16px| 13px |

* この設定値の詳細については[OSの文字サイズ設定変更時の挙動](#OSの文字サイズ設定変更時の挙動)で後述します。

`font:-apple-system-body;`指定した要素で、`font-size`を指定（上書き）してしまうと、Dynamic Typeが**無効**になります。

<dl>
  <dt>NG:</dt>
  <dd>
    <pre>p{
   font-family: -apple-system-body;
   font-size: 16px;
}</pre>
  </dd>
</dl>

`1em`や`100%`といった描画上はサイズが変わらないはずの指定であっても、`font-size`の指定があれば無効になりす。

<dl>
  <dt>NG:</dt>
  <dd>
    <pre>p{
   font-family: -apple-system-body;
   font-size: 100%;
}</pre>
  </dd>
</dl>

子孫要素については挙動が異なり、文字サイズの調整が可能です。
このとき、`font-size`は`%`や`em`、`rem`などの親やルートに対する相対単位である必要があります。

<dl>
  <dt>OK:</dt>
  <dd>
    <pre>ul{
   font-family: -apple-system-body;
}
li{
   font-size: 130%;
}
</pre>
  </dd>
</dl>

それ以外の単位の場合、Dynamic Typeは無効になります。

<dl>
  <dt>NG:</dt>
  <dd>
    <pre>ul{
   font-family: -apple-system-body;
}
li{
   font-size: 20px;
}
</pre>
  </dd>
</dl>

まとめると、以下のいずれかの場合でのみDynamic Typeが有効になります。

* `-apple-system-body`を指定していて、かつその要素に`font-size`の指定がない
* 祖先に`-apple-system-body`を指定していて、要素の`font-size` に`%`や`em`、`rem`などの親やルートに対する相対単位を指定している

## font-familyへの影響
要素に `font:-apple-system-body;` を指定した場合、描画される字体は `font-family:-apple-system;` を指定した場合と同様になります。
* 英数字はSF
* 日本語はHiragino-sans
  * 日本語に1px程度の縮小処理（この処理の結果はComputedStyleには反映されない）

`-apple-system`による日本語縮小処理についてはこちらで解説しています。
https://qiita.com/a_t/items/18693be11bd87f98d212

`font:-apple-system-body;`を指定した後、`font-size`を上書きした場合はDynamic Typeが無効になりますが、`font-famiy`を上書きした場合Dynamic Typeは有効なままです。

そのため、次のような指定で、Dynamic Typeを有効にしつつ字体を変更することができます。

```
div {
    font: -apple-system-body;
    font-family: "Arial", "Hiragino Maru Gothic ProN", sans-serif;
}
```


### OSの文字サイズ設定変更時の挙動
#### iOS
iOSでは、`設定` > `アクセシビリティ`のなかにある`画面表示とテキストサイズ`の`さらに大きな文字`にあるスライダーを変更すると、文字サイズが拡大/縮小されます。（デフォルトではスライダーの中央部分が選択された状態）

このとき、`-apple-system-body`が指定された要素の`font-size`の値も変わります。スライダー位置がデフォルトの場合**17px**で表示されます。

変更された値は、JSの`getComputedStyle`で確認することができます。またブラウザの開発ツールのCSSパネルからも確認できます。

iOSでは、Safariのほかに、Chrome、Firefoxでも同様の挙動になります。

#### macOS
macOSでは、OS全体で文字サイズを変更するような設定は用意されていません。（アプリケーションごとに準備された方法で文字サイズを変更することは可能）
https://support.apple.com/ja-jp/guide/mac-help/mchld786f2cd/mac#apdd3efcf7d62154

しかし、macOSのSafariでは`-apple-system-body`が指定された要素の`font-size`は**13px**に変更されます。

macOSのChromeとFirefoxでは`-apple-system-body;`は無効のため、`font-size`は変更されず、**16px**のままです。


### ブラウザの文字サイズ設定変更時の挙動
iOS Safariではアドレスバーの隣の「ぁあ」というボタンを選択したときに表示されるメニューから、表示の拡大縮小を設定することができます。
iOSの他のブラウザについても、各ブラウザで表示の拡大縮小を設定するオプションを提供している場合があります。

OSではなくブラウザが用意している文字サイズ変更機能では、`font: -apple-system-body;`の有無に関係なく、文字サイズの拡大縮小が行われます。


### まとめ

```
:root{
    font: -apple-system-body;
}

elem{
    font-size: 1rem;
}
```

* 日本語は縮小処理によって1px程度縮小されるため、`1rem`を指定したとき日本語は**16px**相当で、英数字は**17px**で表示される
* macOSのSafariでのみ大きく表示が異なる

#### できるだけ表示の差異をなくしたい場合

```
@font-face {
    font-family: "ff-apple-system";
    src: local(-apple-system);
}

:root{
  font-size:106.25%;
}

@supports (-webkit-touch-callout: none) and (font: -apple-system-body){
  :root{
    font: -apple-system-body;
    font-family: ff-apple-system, sans-serif;
  }
}

elem{
    font-size: 1rem;
}
```

* `font-size:106.25%;`で、すべての環境でルートの`font-size`を17px相当に変更
* `@supports (-webkit-touch-callout: none) and (font: -apple-system-body)` 以下で`font: -apple-system-body;` を設定
   * `-webkit-touch-callout: none`をサポートしていないmacOSのSafariでは、`-apple-system-body`が当たらない
* `-apple-system-body`指定後の`font-family: ff-apple-system, sans-serif;`で、日本語の縮小処理をキャンセル（font-faceを経由して`-apple-system`を指定することで、縮小処理はキャンセルされる）

これにより、どの環境でも
* `rem`の基準値は17px
* 日本語も縮小されず17px相当で表示

となります。

※ font-faceを経由した日本語の縮小処理のキャンセルや、`@supports (-webkit-touch-callout: none)` によるmacOS / Safariの除外は今後の動作を保証するものではないため、バージョンアップによって崩れる可能性があります。