LoginSignup
3
2

More than 3 years have passed since last update.

font-family: serifのみの指定で日本語明朝体が表示されるかチェックする

Posted at

canvasにsans-serifとsansで「あ」を描画して差異があるかどうかを見るという方法です。

デモ

hasJapSerif
function hasJapSerif () {
    const size = 16
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')

    canvas.width = size
    canvas.height = size

    ctx.fillStyle = '#000'
    ctx.textAlign = 'start'
    ctx.textBaseline = 'top'

    ctx.font = size + 'px sans-serif'
    ctx.fillText('', 0, 0);
    const pixels1 = ctx.getImageData(0, 0, size, size).data

    ctx.clearRect(0, 0, size, size)
    ctx.font = size + 'px serif'
    ctx.fillText('', 0, 0);
    const pixels2 = ctx.getImageData(0, 0, size, size).data

    for (let i = 0, ii = size*size*4; i < ii; i++) {
        if (pixels1[i] !== pixels2[i]) {
            return true
        }
    }
    return false
}

これを利用して、Androidなど日本語明朝体がバンドルされてないデバイスのみ、日本語明朝体のウェブフォントを読み込むということができます。

if (!hasJapSerif()) {
    const link = document.createElement('link')
    link.rel = 'stylesheet'
    link.href = 'https://fonts.googleapis.com/css?family=Noto+Serif+JP'
    document.head.appendChild(link)
}

去年のAdvent Calendarでシンプルにfont-familyを指定したい記事を書きました。

その記事で全ての主要なデバイスで日本語明朝体を表示する方法の一つに、UserAgentを見てAndroidの場合はGoogleFontsのNotoSerifを読み込むという雑なサンプルコードを紹介しました。

その記事を書いた2018年末、そしてこの2019年末も、主要デバイスで日本語明朝体をバンドルしてないのはAndoridだけですが、この判定方法はもちろんスマートではないですし、今後、Androidで日本語明朝体がバンドルされて font-family: serif の指定だけで日本語明朝体が表示されるようになる可能性もあるので、ちゃんとしたものを投稿しました。

わざわざ日本語明朝体がバンドルされてない場合のみウェブフォントを読み込み適用させる方法をとりたいのは、読み込むリソースの容量をできるだけ小さくしたいだけでなく、ウェブサイトのフォントはどのデバイスでもできるだけ同じにするのではなく、そのデバイスにバンドルされてる標準なフォントをできるだけ使う、という考え方をしてるのもあります。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2