はじめに
Google Fontsのリンクを<head>に貼るだけでフォントが使える手軽さは魅力ですが、実運用で気になる点もあります。フォントの配信先が自分のサーバーではなく外部CDNになること、EU圏ではIPアドレス送信によるプライバシー問題でGoogle Fontsの利用が問題視された事例があったこと、そしてGoogle側の更新でフォントファイルが予告なく差し替わる可能性があることです。
Fontsourceは、この「外部CDN頼み」を解消するために生まれたプロジェクトです。2,000種類を超えるオープンソースフォントを、バージョン固定されたnpmパッケージとして配布しており、npm installした時点のフォントファイルがそのままビルドに焼き込まれます。自分のアプリと同じ場所からフォントを配信できるので、DNS解決やTCP接続の往復も1回分減らせます。
とはいえ、読むより触った方が早いと思います。ウェイトごとに分割されたCSSを読み込むだけで、太字が「本物のBoldウェイト」になる様子を確認できるサンプルを用意したので、先に挙動を見たい方はこちらからどうぞ。
Fontsourceとは
Fontsourceは、Google Fontsをはじめとするオープンソースフォントを「きれいに梱包されたnpmパッケージ」として配布するプロジェクトです。フォント1つにつき@fontsource/robotoのようなパッケージが対応しており、必要なフォントだけを依存関係として追加できます。
主な特徴
- バージョン固定 -
package.jsonにバージョンが記録されるため、フォントの中身が意図せず変わることがありません - ウェイト・スタイル単位の分割インポート -
@fontsource/roboto/700.cssのように、使うウェイトだけを個別にインポートしてバンドルサイズを抑えられます - Variable Fonts対応 -
@fontsource-variable/*パッケージでは、1つのフォントファイルで太さや幅を無段階に変化させられます - セルフホスト前提の設計 - 自分のドメインからフォントを配信できるため、外部トラッキングを気にする必要がありません
- jsDelivr経由のCDNも用意 - npmパッケージを使わず、CDNのURLを直接
<link>で読み込む使い方もサポートしています
インストール
使いたいフォントごとにパッケージが分かれているので、フォント名を指定してインストールします。
npm install @fontsource/roboto
Variable Fontsを使う場合はパッケージ名が@fontsource-variable/から始まります。
npm install @fontsource-variable/roboto-flex
Fontsourceのサンプルを動かす
Fontsourceの@fontsource/robotoは、ウェイトごとにCSSファイルが分かれています。下のサンプルでは「太字で表示する」だけをチェックすると、対応するBoldの書体データを読み込んでいないため、ブラウザが既存の文字を機械的に太らせる**擬似的な太字(synthetic bold)**が表示されます。続けて「700.cssを読み込む」もチェックすると、@fontsource/roboto/700.cssが追加され、本物のBoldウェイトの字形に切り替わります。
要点だけを抜き出すと、実際のコードはこれだけです。
// 使うウェイトのCSSだけをインポートする
import '@fontsource/roboto/400.css'
import '@fontsource/roboto/700.css'
const el = document.querySelector('#sample')
el.style.fontFamily = 'Roboto, sans-serif'
el.style.fontWeight = '700' // 700.cssがあるので本物のBoldが使われる
実際に動かせるサンプルが下です。チェックボックスの組み合わせを変えて、文字の太さがどう変わるか見比べてみてください。
「太字で表示する」を単独でオンにすると、ブラウザが手持ちの400ウェイトを引き伸ばして太字らしく見せているだけなので、字形がやや不自然に太ります。「700.cssを読み込む」も合わせてオンにすると、Fontsourceが配信する専用のBoldファイルに切り替わり、字形そのものが変わることが確認できます。これが「必要なウェイトだけをインポートする」設計の実体です。
基本的な使い方
多くの場合は、アプリのエントリーファイルでフォントをインポートし、CSSのfont-familyで参照するだけで使えます。
// src/main.tsx や _app.tsx などエントリーファイルの先頭で
import "@fontsource/roboto/400.css";
import "@fontsource/roboto/700.css";
import "@fontsource/roboto/400-italic.css";
import "@fontsource/roboto/700-italic.css";
body {
font-family: "Roboto", sans-serif;
}
ViteやNext.js、Remixのようなバンドラー環境であれば、node_modules内のCSSとフォントファイルがそのままビルド成果物に含まれます。npmパッケージを使わない場合は、jsDelivr経由のCDN URLを直接<link>で読み込むことも可能です。
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@fontsource/roboto@5.3.0/400.css"
/>
実践的なユースケース
Variable Fontsで軸をリアルタイムに操作する
@fontsource-variable/roboto-flexのようなVariable Fontsパッケージは、太さ(wght)や幅(wdth)といった複数の軸を1つのフォントファイルに持たせています。通常のフォントのように「400番のファイル」「700番のファイル」を別々に用意する必要がなく、CSSのfont-weightやfont-stretchに任意の数値を指定するだけで、その場で字形を連続的に変化させられます。
/* Roboto Flex Variable を読み込むと、
font-weight: 100〜1000、font-stretch: 25%〜151% が
1ファイルの中で無段階に変化する */
.headline {
font-family: "Roboto Flex Variable", sans-serif;
font-weight: 850; /* 100〜1000の任意の値 */
font-stretch: 140%; /* 25%〜151%の任意の値 */
}
下のサンプルでは、2本のスライダーでfont-weightとfont-stretchを直接動かせます。@fontsource-variable/roboto-flexのfull.cssを読み込んでいるので、細身から極太まで、狭い字幅から広い字幅まで途切れなく変化する様子が見られます。
太さのスライダーを100付近まで下げると極細に、1000近くまで上げると極太になります。幅のスライダーを25%側に振ると縦長に圧縮された字形になり、151%側では横に広がった字形になります。ウェイトごとにファイルを増やすのではなく、この1ファイルだけで見出し用の極太から本文用の細字まで賄えるのがVariable Fontsの利点です。
複数フォントを切り替えて比較する
Fontsourceはフォントごとに独立したパッケージなので、用途別に複数のフォントを組み合わせて使うのも簡単です。ここでは@fontsource/roboto(汎用のUIフォント)、@fontsource/fira-code(等幅のコード用フォント)、@fontsource/noto-sans-jp(日本語対応フォント)の3つを同時に読み込み、テキストエリアの内容を変えずにフォントだけ切り替えて見比べます。
// 用途別に別々のFontsourceパッケージを読み込む
import '@fontsource/roboto/400.css'
import '@fontsource/fira-code/400.css'
import '@fontsource/noto-sans-jp/400.css'
function applyFont(name) {
preview.style.fontFamily = `'${name}', sans-serif`
}
下のサンプルでは、セレクトボックスでフォントを切り替えられます。日本語を入力してNoto Sans JPに切り替えたり、コードっぽい文字列を入力してFira Codeの等幅表示を確認したりしてみてください。
Fira Codeに切り替えると等幅フォント特有の縦の揃い方が見え、Noto Sans JPに切り替えると日本語部分が正しく表示されます。フォントごとにパッケージが独立しているため、必要なフォントだけをプロジェクトの依存関係に加えられる点がFontsourceらしい設計です。
まとめ
Fontsourceは、Webフォントを「外部CDNから借りるもの」から「自分のプロジェクトに固定されたアセット」に変える発想のライブラリです。ウェイト・スタイル単位の分割インポートでバンドルサイズを抑えつつ、Variable Fontsパッケージを使えば1ファイルで幅広い表現にも対応できます。Google Fontsのプライバシー面や配信の安定性が気になっている方は、まず使っているフォントの@fontsource/パッケージが存在するか探してみてください。
