指定したフォントに特定のスタイル(太さや斜体)がない時にブラウザが生成する機能(フォントシンセシス)を検証してみた

例えばGoogle FontsからCDNでNoto Sans JPのフォントを読み込んでいるとします。
その時に、ウェイト400(Regular)だけをインストールしている時に700(Bold)を指定したらどうなるかが気になり調べました。

# 検証内容
- GoogleFontsからCDNでフォントを読み込む
- 特定のスタイルを読み込んでいないバージョンでの表示と、全て読み込んでいるバージョンでの表示の2パターンで検証
- これで文字が実際にどうみえるのかを検証

# 結論
`フォントシンセシス(font synthesis)`という機能があり、指定したフォント(`font-family`)がCSSで設定されている特定のスタイルを持っていないｂでもブラウザが疑似的に生成して表示してくれる

## フォントシンセシス(font synthesis)とは？
例えば、`font-family`でNotoSansJPを指定して、GoogleFontsのCDNで400(Regular)だけを読み込んでいる例を考えます。
この場合、400(Regular)以外は読み込まれていない為、通常次のような表示は出来ないです。
- `font-weight: 700`のようなBold表示
- `font-style: italic`のような斜体表示
しかし、ブラウザがそれっぽく太文字と斜体を表現してくれます。
それがフォントシンセシスという機能です。

https://developer.mozilla.org/ja/docs/Web/CSS/font-synthesis

この太さや斜体の他にも、スモールキャップや下付き文字と上付き文字の設定もできます。
しかし、基本的には太字と斜体しか使わないのと、対応ブラウザ的にも下付き文字と上付き文字の設定は使わないと思います。

## ブラウザ対応状況(2025/1/16現在)と仕様
以下対応状況です 

https://caniuse.com/?search=font-synthesis

### 太さの設定 (`font-synthesis-weight`)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297279/f567652b-b0b7-0265-ab75-14115632b038.png)

https://caniuse.com/?search=font-synthesis-weight

https://developer.mozilla.org/ja/docs/Web/CSS/font-synthesis-weight

### 斜体の設定(`font-synthesis-style`)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297279/8c54b6a5-4e53-5df8-1b10-d5ea83926296.png)

https://caniuse.com/?search=font-synthesis-style

https://developer.mozilla.org/ja/docs/Web/CSS/font-synthesis-style

### スモールキャップの設定(`font-synthesis-small-caps`)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297279/7c0fc191-e932-dd16-762a-cc6b3680ef24.png)

https://caniuse.com/?search=font-synthesis-small-caps

https://developer.mozilla.org/ja/docs/Web/CSS/font-synthesis-small-caps

### 下付き文字と上付き文字の設定(`font-synthesis-position`)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297279/767e6ade-4e6c-5230-6872-1e78de9bf277.png)

https://caniuse.com/?search=font-synthesis-position

https://developer.mozilla.org/ja/docs/Web/CSS/font-synthesis-position


# 検証してみた内容
今回は太文字と斜体の検証をしてみた。

検証に使用したソースコードはGitHubに上げておくので確認してみてください。

https://github.com/feit-curacao/font-synthesis-test

## 太文字の検証
フォントのウェイトを400(Regular)だけ読み込み、その状態で`font-weight:bold`を設定した。
比較対象として、700(Bold)も読み込まれたものを合わせて見ていく。

### 検証用のCSS
```css:スタイルの指定
body {
    font-family: 'Noto Sans JP', sans-serif;
    font-size: 20px;
}
span {
    font-weight: 400;
}

b {
    font-weight: 700;
}

.no-synthes {
    font-synthesis-weight: none;
    font-weight: 700;
}
```


### 検証用のHTML
```html:HTMLの設定
<span>Noto sans JP:全ウェイトを読み込んだ</span><br>
<span>ここで<b>Bold(700)を指定して</b>みる</span><br>
<b>Bold(700)の表示</b>
<b>0123456789</b>
<b>ABCDEFGHIJKLMNOPQRSTUVWXYZ</b>
<p class="no-synthes">font-synthesis-weight:noneに設定してみたBold(700)</p>
```

この2つをベースで使っていく。
`no-synthes`クラスが、今回のフォントシンセシス無効の物になります。

これにGoogle FontsのCDNで分けていく
```html: Google Fonts読み込み例
<!-- Noto Sans JP 全ウェイトを読み込み -->
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100..900&display=swap" rel="stylesheet">

<!-- Noto Sans JP 400だけを読み込み -->
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap" rel="stylesheet">
```

これで有り無しを実際に比較してみた。


### 実際の表示画面
まずは、400(Regular)しか読み込んでいないのに700(bold)を使った例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297279/34249b59-0575-07d5-bc83-6778f7d739b2.png)
このBoldはブラウザが生成したそれっぽいBoldの形です。

次に、すべてのウェイトをきちんと読み込んでいる例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297279/a293e050-8c01-173a-efe9-ab5fdb31bacc.png)
こちらが正しいNotoSansJPのBoldです。

最後に両方ならべて比べてみた(左が400のみ、右が全て）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297279/adef4bb0-572c-c7a3-b723-e0eb7b79c270.png)
並べて比べてみてもよく見ると違うけどぱっと見あまりわからないかも。
うまくブラウザが生成できてるってことなのか？

今度はBoldの文字だけ拡大して並べてみた(左がブラウザ産、右が正しいNotoSansJP)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297279/008b2f58-3c56-f2e4-43de-6b5f619a487b.png)
ここまで大きくしてみると確かに違いがわかる。

### 追加検証：Montserratでやってみた
日本語書体だけではなく他だとどうなるかと思い、Montserratを使って検証してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297279/36fc7949-571d-540d-9fbc-7a9ed7fbb9c0.png)

ここまでくると一目瞭然ですね！

## 斜体の検証
太文字と同じように検証をしていきます。

### 検証用のHTML
```css: スタイルの設定
body {
    font-family: "Montserrat", serif;
    font-size: 20px;
    font-weight: 400;
}
span {
    font-style: normal;
}

i {
    font-style: italic;
}

.no-synthes {
    font-synthesis-style: none;
    font-style: italic;
}
```

```html: HTMLの設定
<i>0123456789</i><br>
<i>ABCDEFGHIJKLMNOPQRSTUVWXYZ</i><br>
<p class="no-synthes">font-synthesis-style:none</p>
```

### 実際の表示画面
左はブラウザが生成したItalicで、右が本物のMontserratの斜体です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297279/e26a816f-2a56-b9c1-51e7-9c4b525d5cc5.png)
う～んー・・・
ブラウザの生成機能がすごいという事ですね。( ~~決して違いがわからなくてあきらめたわけじゃない~~ )


# そもそもなんでこれが気になったか？
デジタル庁デザインシステム-v1.4.3

https://www.figma.com/design/16xHwiXu2ozgr0OI5XmeNS/%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E5%BA%81%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0-v1.4.3-(Community)?node-id=6494-5399

こちらのFigmaにこのような表記がありました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297279/25ffa4bf-99a1-32cc-1991-0a06dd33856f.png)
この疑似Boldってなんだ？
ということで調べ始めたのがきっかけです。

これは多分、デザインできちんとフォントのBold設定を使わずに文字をコピペとかで重ねて太くするのはダメということなのでは？と今は思っているのですが、初めはブラウザの事かと思い気になり調べ始めた次第です。

# 終わりに
デザインと正確に合わせるときにフォントの読み込み漏れなどがあったら指摘されそうなのでそういったのを検出できるものがあったらいいなーとは思うのですが、基本的にテスト段階で`font-synthesis-weight`を`none`にしとけばすぐ気づけるとは思います。

誰かの何かで役に立てたら幸いです。
間違いなどがありましたらコメント頂けますと嬉しいです！
ありがとうございました。