フォント最適化

next/font はフォント(カスタムフォントを含む)を自動的に最適化し、プライバシーとパフォーマンスを向上させるために外部ネットワークリクエストを削除します。

🎥 動画で学ぶ: next/font の使い方 → YouTube (6分)

next/font には自動セルフホスティング機能が組み込まれており、_あらゆる_フォントファイルを最適にロードできます。CSSの size-adjust プロパティを使用することで、レイアウトシフトをゼロに抑えたウェブフォントの読み込みが可能です。

この新しいフォントシステムでは、パフォーマンスとプライバシーに配慮しながらすべてのGoogleフォントを簡単に使用できます。CSSとフォントファイルはビルド時にダウンロードされ、他の静的アセットと一緒にセルフホストされます。ブラウザからGoogleへのリクエストは送信されません。

Googleフォント

Googleフォントを自動的にセルフホストできます。フォントはデプロイメントに含まれ、デプロイメントと同じドメインから提供されます。ブラウザからGoogleへのリクエストは送信されません。

使用したいフォントを next/font/google から関数としてインポートします。最高のパフォーマンスと柔軟性を得るために、可変フォントの使用を推奨します。

import { Inter } from 'next/font/google'

// 可変フォントを読み込む場合、フォントウェイトを指定する必要はありません
const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
})

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className={inter.className}>
      <body>{children}</body>
    </html>
  )
}
import { Inter } from 'next/font/google'

// 可変フォントを読み込む場合、フォントウェイトを指定する必要はありません
const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
})

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={inter.className}>
      <body>{children}</body>
    </html>
  )
}

可変フォントが使用できない場合は、ウェイトを指定する必要があります:

import { Roboto } from 'next/font/google'

const roboto = Roboto({
  weight: '400',
  subsets: ['latin'],
  display: 'swap',
})

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className={roboto.className}>
      <body>{children}</body>
    </html>
  )
}
import { Roboto } from 'next/font/google'

const roboto = Roboto({
  weight: '400',
  subsets: ['latin'],
  display: 'swap',
})

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={roboto.className}>
      <body>{children}</body>
    </html>
  )
}

配列を使用して複数のウェイトやスタイルを指定できます:

app/layout.js
const roboto = Roboto({
  weight: ['400', '700'],
  style: ['normal', 'italic'],
  subsets: ['latin'],
  display: 'swap',
})

豆知識: 複数の単語を含むフォント名にはアンダースコア(_)を使用します。例: Roboto MonoRoboto_Mono としてインポートします。

サブセットの指定

Googleフォントは自動的にサブセット化されます。これによりフォントファイルのサイズが縮小され、パフォーマンスが向上します。プリロードするサブセットを定義する必要があります。preloadtrue なのにサブセットが指定されていない場合、警告が表示されます。

関数呼び出しに追加することで指定できます:

const inter = Inter({ subsets: ['latin'] })
const inter = Inter({ subsets: ['latin'] })

詳細はフォントAPIリファレンスをご覧ください。

複数フォントの使用

アプリケーションで複数のフォントをインポートして使用できます。2つのアプローチがあります。

1つ目のアプローチは、フォントをエクスポート、インポートし、必要な場所で className を適用するユーティリティ関数を作成する方法です。これにより、フォントがレンダリングされたときのみプリロードされます:

import { Inter, Roboto_Mono } from 'next/font/google'

export const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
})

export const roboto_mono = Roboto_Mono({
  subsets: ['latin'],
  display: 'swap',
})
import { Inter, Roboto_Mono } from 'next/font/google'

export const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
})

export const roboto_mono = Roboto_Mono({
  subsets: ['latin'],
  display: 'swap',
})
import { inter } from './fonts'

export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" className={inter.className}>
      <body>
        <div>{children}</div>
      </body>
    </html>
  )
}
import { inter } from './fonts'

export default function Layout({ children }) {
  return (
    <html lang="en" className={inter.className}>
      <body>
        <div>{children}</div>
      </body>
    </html>
  )
}
import { roboto_mono } from './fonts'

export default function Page() {
  return (
    <>
      <h1 className={roboto_mono.className}>My page</h1>
    </>
  )
}
import { roboto_mono } from './fonts'

export default function Page() {
  return (
    <>
      <h1 className={roboto_mono.className}>My page</h1>
    </>
  )
}

上記の例では、Inter がグローバルに適用され、Roboto Mono は必要に応じてインポートして適用できます。

別の方法として、CSS変数を作成し、好みのCSSソリューションで使用できます:

import { Inter, Roboto_Mono } from 'next/font/google'
import styles from './global.css'

const inter = Inter({
  subsets: ['latin'],
  variable: '--font-inter',
  display: 'swap',
})

const roboto_mono = Roboto_Mono({
  subsets: ['latin'],
  variable: '--font-roboto-mono',
  display: 'swap',
})

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className={`${inter.variable} ${roboto_mono.variable}`}>
      <body>
        <h1>My App</h1>
        <div>{children}</div>
      </body>
    </html>
  )
}
import { Inter, Roboto_Mono } from 'next/font/google'

const inter = Inter({
  subsets: ['latin'],
  variable: '--font-inter',
  display: 'swap',
})

const roboto_mono = Roboto_Mono({
  subsets: ['latin'],
  variable: '--font-roboto-mono',
  display: 'swap',
})

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={`${inter.variable} ${roboto_mono.variable}`}>
      <body>
        <h1>My App</h1>
        <div>{children}</div>
      </body>
    </html>
  )
}
app/global.css
html {
  font-family: var(--font-inter);
}

h1 {
  font-family: var(--font-roboto-mono);
}

上記の例では、Inter がグローバルに適用され、すべての <h1> タグは Roboto Mono でスタイルされます。

推奨事項: 新しいフォントはクライアントがダウンロードする追加リソースとなるため、複数フォントの使用は控えめにしてください。

ローカルフォント

next/font/local をインポートし、ローカルフォントファイルの src を指定します。最高のパフォーマンスと柔軟性を得るために、可変フォントの使用を推奨します。

import localFont from 'next/font/local'

// フォントファイルは `app` 内に配置できます
const myFont = localFont({
  src: './my-font.woff2',
  display: 'swap',
})

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className={myFont.className}>
      <body>{children}</body>
    </html>
  )
}
import localFont from 'next/font/local'

// フォントファイルは `app` 内に配置できます
const myFont = localFont({
  src: './my-font.woff2',
  display: 'swap',
})

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={myFont.className}>
      <body>{children}</body>
    </html>
  )
}

単一のフォントファミリーに対して複数のファイルを使用したい場合、src を配列にできます:

const roboto = localFont({
  src: [
    {
      path: './Roboto-Regular.woff2',
      weight: '400',
      style: 'normal',
    },
    {
      path: './Roboto-Italic.woff2',
      weight: '400',
      style: 'italic',
    },
    {
      path: './Roboto-Bold.woff2',
      weight: '700',
      style: 'normal',
    },
    {
      path: './Roboto-BoldItalic.woff2',
      weight: '700',
      style: 'italic',
    },
  ],
})

詳細はフォントAPIリファレンスをご覧ください。

Tailwind CSSとの併用

next/fontCSS変数 を通じて Tailwind CSS と併用できます。

以下の例では、next/font/google から Inter フォントを使用しています(Googleフォントまたはローカルフォントのいずれでも使用可能です)。variable オプションを使用してフォントを読み込み、CSS変数名を定義し inter に割り当てます。次に、inter.variable を使用してHTMLドキュメントにCSS変数を追加します。

import { Inter, Roboto_Mono } from 'next/font/google'

const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
  variable: '--font-inter',
})

const roboto_mono = Roboto_Mono({
  subsets: ['latin'],
  display: 'swap',
  variable: '--font-roboto-mono',
})

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className={`${inter.variable} ${roboto_mono.variable}`}>
      <body>{children}</body>
    </html>
  )
}
import { Inter, Roboto_Mono } from 'next/font/google'

const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
  variable: '--font-inter',
})

const roboto_mono = Roboto_Mono({
  subsets: ['latin'],
  display: 'swap',
  variable: '--font-roboto-mono',
})

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={`${inter.variable} ${roboto_mono.variable}`}>
      <body>{children}</body>
    </html>
  )
}

最後に、CSS変数を Tailwind CSS設定 に追加します:

tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './pages/**/*.{js,ts,jsx,tsx}',
    './components/**/*.{js,ts,jsx,tsx}',
    './app/**/*.{js,ts,jsx,tsx}',
  ],
  theme: {
    extend: {
      fontFamily: {
        sans: ['var(--font-inter)'],
        mono: ['var(--font-roboto-mono)'],
      },
    },
  },
  plugins: [],
}

これで、font-sansfont-mono ユーティリティクラスを使用して要素にフォントを適用できます。

プリロード

サイトのページでフォント関数が呼び出されると、そのフォントはグローバルに利用可能ではなく、すべてのルートでプリロードされません。代わりに、フォントは使用されるファイルのタイプに基づいて関連するルートでのみプリロードされます:

  • ユニークページ の場合、そのページのユニークルートでプリロードされます
  • レイアウト の場合、レイアウトで囲まれたすべてのルートでプリロードされます
  • ルートレイアウト の場合、すべてのルートでプリロードされます

フォントの再利用

localFont またはGoogleフォント関数を呼び出すたびに、そのフォントはアプリケーション内で1つのインスタンスとしてホストされます。したがって、複数のファイルで同じフォント関数を読み込むと、同じフォントの複数のインスタンスがホストされます。このような状況では、以下の方法を推奨します:

  1. 共有ファイルでフォントローダー関数を呼び出す
  2. 定数としてエクスポートする
  3. このフォントを使用したい各ファイルで定数をインポートする