ウェブフォントを遅延読み込みする簡単な実装
ページの初回読み込み時から @font-face
でウェブフォントを読み込もうとしていると、どうもレンダリングが遅くなる。font-display: swap
もなんだか効いてない気がする。そこで、いさぎよく window.onload
以降にウェブフォントを遅延読み込みすることにした。
ココでは、OS 問わず日本語対応の等幅フォントを表示するため、Noto Sans Mono CJK JP を遅延読み込みすることにする。
サンプル
以下で実装サンプルを確認できる。
- デモ : Easy Lazy Loading Web Font
- コード : frontend-sandboxes/index.html at master · Neos21/frontend-sandboxes
サンプルでは、ページ読み込みから3秒後、初めて Web フォントを読み込むよう遅延させている。
「Remove」と「Add」ボタンは、遅延読み込み時に html
要素に付与しているクラス名を付けたり外したりできる。スワップの挙動を手動で再現できる。
@font-face
で定義したウェブフォントはいつロードされるか
ところで、@font-face
で定義したウェブフォントは、どのタイミングでロードされるのか。自分が調べたところ、
- ただ
@font-face
を定義しただけでは、ウェブフォントは読み込まれない - HTML 中に適用する対象がないセレクタでウェブフォントを指定していても、ウェブフォントは読み込まれない
- 例えばページ中に
div
要素が一つもない状態で、div { font-family: "My Web Font"; }
という CSS 指定があっても、そのウェブフォントはロードされない
- 例えばページ中に
- HTML 中に適用対象となる要素が存在すると、初めてウェブフォントが読み込まれる
つまり、ウェブフォントを使うような指定が CSS として記述してあっても、それが使われている HTML 要素がページ中になければ、その CSS の記述が無視されて、ウェブフォントも読み込まれないワケだ。
遅延読み込みを前提とした CSS を書く
ということなので、予め次のような CSS を用意しておく分には、ウェブフォントはロードされない。
@font-face {
font-family: "Noto Sans Mono CJK JP Web";
src: local("NotoSansMonoCJKjp-Regular"),
local("Noto Sans Mono CJK JP Regular"),
local("Noto Sans Mono CJK JP"),
url("https://cdn.jsdelivr.net/npm/@neos21/japanese-monospaced-fonts@1.0.2/NotoSansMonoCJKjp-Regular.woff2") format("woff2"),
url("https://unpkg.com/@neos21/japanese-monospaced-fonts@1.0.2/NotoSansMonoCJKjp-Regular.woff2") format("woff2"),
url("https://cdn.jsdelivr.net/npm/@neos21/japanese-monospaced-fonts@1.0.2/NotoSansMonoCJKjp-Regular.woff") format("woff"),
url("https://unpkg.com/@neos21/japanese-monospaced-fonts@1.0.2/NotoSansMonoCJKjp-Regular.woff") format("woff"),
url("https://cdn.jsdelivr.net/npm/@neos21/japanese-monospaced-fonts@1.0.2/NotoSansMonoCJKjp-Regular.otf") format("opentype"),
url("https://unpkg.com/@neos21/japanese-monospaced-fonts@1.0.2/NotoSansMonoCJKjp-Regular.otf") format("opentype"),
url("https://cdn.jsdelivr.net/npm/@japanese-monospaced-fonts/noto-sans-mono-cjk-jp@1.0.1/NotoSansMonoCJKJP-Regular.otf") format("opentype"),
url("https://unpkg.com/@japanese-monospaced-fonts/noto-sans-mono-cjk-jp@1.0.1/NotoSansMonoCJKJP-Regular.otf") format("opentype");
font-display: swap;
}
/* 通常のスタイル : ウェブフォントを読み込まない */
html { font-family: monospace; }
/* html 要素に class が振られた場合 : 通常 .loaded クラスを振らなければ、この指定はどこにも使われず、ウェブフォントはロードされない */
html.loaded { font-family: "Noto Sans Mono CJK JP Web", monospace; }
遅延読み込みのためのスクリプト
先程用意した html.loaded
というセレクタを有効にするため、window.onload
のタイミング以降で html
要素に CSS クラスを振る、簡単な JS を書く。
window.addEventListener('load', () => {
setTimeout(() => {
document.querySelector('html').classList.add('loaded');
}, 1);
});
コレだけで OK。この CSS クラスが振られた瞬間からウェブフォントが読み込まれ、読み込みが完了したら画面に適用される。
Noto Sans Mono CJK JP はファイルサイズが大きいので、ロードに10秒程度かかることもある。ページへの反映がかなり遅れるかもしれないが、ページの初回読み込みは一切ブロックしないので、一長一短。