⌨️

[next.js 14] google fontが地味に最高です

2024/01/20に公開

next/font/googleを使うメリット

普通にcssでインポートしてfont-familyで指定すればとりあえず使えるけど、あえてnext/font/googleを使うことで得られるメリットも大

layout shiftを防ぐ

一番のメリット: 初期描画のガタツキを防げられる

静的アセットとしてホストされる

つまりフォントを他の画像などの静的ファイルと同様にホストされるので、ユーザーがアプリケーションをアクセスするときにわざわざgoogleまで行ってフォントのリクエストしなくて済んで、パフォーマンスの向上に繋がる。

Next.js downloads font files at build time and hosts them with your other static assets. This means when a user visits your application, there are no additional network requests for fonts which would impact performance.[1]

使い方・基本

Google Fontで見つけたフォント名を_で繋げればnext/font/googleからimportできる
英語フォントはもちろん、日本語フォント、わけわからん言語のフォント全部同じルールでimportして使える

importしてフォント定義しておく

/hogehoge/fonts.ts
import { Aoboshi_One } from 'next/font/google';

export const aoboshiOne = Aoboshi_One({
  subsets: ['latin'],
  weight: '400',
});

定義したフォントを別のコンポーネントにimportしてclassNameとして渡す

/hogehoge/your-component.tsx
import { aoboshiOne } from '@/hogehoge/fonts'
// (中略)
<div className={aoboshiOne.className}></div>

完了。

多言語アプリのfonts.tsはこうなっているかもしれない

/hogehoge/fonts.ts
import {
  Pacifico, // 英語フォント
  ZCOOL_QingKe_HuangYou, // 中国語フォント
  Aoboshi_One, // 日本語フォント
} from 'next/font/google';

export const pacifico = Pacifico({ 
  subsets: ['latin'], 
  weight: '400' 
});

export const zcoolQingKeHuangYou = ZCOOL_QingKe_HuangYou({
  subsets: ['latin'],
  weight: '400',
});
export const aoboshiOne = Aoboshi_One({
  subsets: ['latin'],
  weight: '400',
});

font-weightの指定について

google fontはフォントによってfont-weight一種類しかないものも多いが、複数font-weightがある場合、使うものをピックアップして配列として指定してあげる

/assets/styles/fonts
import { Montserrat_Alternates } from 'next/font/google'

export const maFont = Montserrat_Alternates({
  subsets: ['latin'],
  weight: ['100', '200', '300', '400', '500', '600', '700', '800', '900'],
})

使うときのfont-weightの指定方法は複数ある

別のcssクラスでfont-weight指定

/hogehoge/your-component.tsx
import s from './layout.module.scss'
import { maFont } from '@/assets/styles/fonts'
// (中略)
<div className={[s.MarketingLayout, maFont.className].join(' ')}></div>
layout.module.scss
.MarketingLayout{
    font-weight: 900;
}

インラインでfont-weight指定

/hogehoge/your-component.tsx
import { maFont } from '@/assets/styles/fonts'
// (中略)
<div className={maFont.className} style={{ fontWeight: 900 }}></div>

なんならfontFamilyもinlineで入れちゃうなら

/hogehoge/your-component.tsx
import { maFont } from '@/assets/styles/fonts'
// (中略)
<div style={{ fontFamily: maFont.style.fontFamily, fontWeight: 900 }}></div>

NextFontオブジェクトについて

fontFamily: hogeFont.style.fontFamilyで指定できるように、NextFontの型を調べると

export type NextFont = {
    className: string;
    style: {
        fontFamily: string;
        fontWeight?: number;
        fontStyle?: string;
    };
};
  • hogeFont.classNameで指定すると、{fontFamily: hogehoge;}を持つCSSクラスが追加される
  • styleをインラインで指定するなら、hogeFont.styleからプロパティをとれる

inline styleであれば、外部ライブラリーのコンポーネントでも簡単にgoogle fontを使うことができた

例)supabaseのauth
'use client'
import { Auth } from '@supabase/auth-ui-react'
import { ThemeSupa } from '@supabase/auth-ui-shared'
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs'
import { Database } from '@/types/supabase'

import { maFont } from '@/assets/styles/fonts'

export default function AuthForm() {
  const supabase = createClientComponentClient<Database>()

  return (
    <Auth
      supabaseClient={supabase}
      view="sign_up"
      appearance={{
        theme: ThemeSupa,
        style: {
          label: { fontFamily: maFont.style.fontFamily },
          input: { fontFamily: maFont.style.fontFamily },
          button: { fontFamily: maFont.style.fontFamily },
        },
      }}
      redirectTo={`${process.env.NEXT_PUBLIC_CALLBACK_URL}/auth/callback`}
    />
  )
}
脚注
  1. 参考: next.js公式チュートリアル ↩︎

Discussion