フォント最適化

文字が一瞬入れ替わる、あれ

Web フォントを使ったページを開くと、最初は見慣れた書体で出て、少し遅れて狙った書体に入れ替わることがあります。行の幅まで変わるので、読み始めた場所が動いて落ち着きません。

原因は、フォントのファイルを外部のサーバーから取ってくるところにあります。CSS を読んで、そこに書かれたフォントの場所を知って、そこから取りに行く、という順番になるので、文字が出てからフォントが届くまでの空白が生まれます。

next/font に任せる

Next.js は next/font でこれを解きます。Google Fonts なら next/font/google から、使いたい書体の名前をそのまま読み込みます。

import { Inter } from "next/font/google"; const inter = Inter({ subsets: ["latin"] });

ビルドのときにフォントのファイルを自分のサイトに取り込むので、外部サーバーへ取りに行く往復が無くなります。取ってくる URL がユーザーの環境ごとに変わらないため、外部への通信そのものも減ります。

subsets は、その書体のうちどの文字を使うかです。英数字だけなら latin を指定しておくと、要らない文字のぶんを持ってこずに済みます。太さを選べる書体では weight も渡します。

返ってくるのは className

呼び出した結果は、className を持つオブジェクトです。これを付けた要素とその中身に、その書体が効きます。

<body className={inter.className}>

サイト全体を同じ書体にしたいならルートレイアウトの body に付けます。見出しだけ別の書体にしたいときは、その見出しに別の className を付けます。文字列をつなぐときは、いつもの className と足し算でつなげます。

<h1 className={notoSansJp.className + " site-title"}>fleama</h1>

書体を呼び出す行は、関数の外側に1回だけ書きます。描くたびに呼ぶ書き方は Next.js が受け付けません。

演習

fleama の本文と見出しに、それぞれ別の書体を当てます。

ヒント

layout.tsx
page.tsx
プレビュー

できているか

  • next/font/google から書体を読み込んでいる
  • subsets を渡して呼び出している
  • 本文全体に Inter の className を付けている
  • サイト名に Noto Sans JP が当たっている
  • 元からある site-title も残っている
  • サイト名がそのまま出ている