Skip to content

Next.js 13 与 Tailwind CSS 集成自定义本地字体

问题概述

在 Next.js 13 项目中结合 Tailwind CSS 使用自定义本地字体时,开发者常会遇到字体无法正确加载或应用的问题。典型表现包括:

  • 配置了 @next/font/local 但页面未显示预期字体
  • Tailwind 未正确识别自定义字体变量
  • 多字重(如粗体、斜体)处理困难
  • 字体路径引用错误导致404错误

根本原因通常在于配置步骤遗漏关键环节,未能完整实现 Next.js 的字体优化机制与 Tailwind 样式的集成。

完整解决方案

前置准备

  1. 移除旧包(如已安装)

    bash
    npm uninstall @next/font
  2. 字体文件放置 将字体文件(如 .woff2)放入 /public/fonts 目录

    public/
    └── fonts/
        ├── Surt-Normal-Regular.woff2
        ├── Surt-Normal-Bold.woff2
        └── Surt-Normal-Semibold-Italic.woff2

路径提示

Next.js 会自动提供 /public 目录下的文件,因此无需自定义路由

步骤1: 配置字体加载

使用 app/ 目录(推荐方式)

/app/layout.tsx 中配置:

jsx
import localFont from 'next/font/local';

// 配置多个字重变体
const surt = localFont({
  src: [
    {
      path: '../public/fonts/Surt-Normal-Regular.woff2',
      weight: '400',
      style: 'normal'
    },
    {
      path: '../public/fonts/Surt-Normal-Bold.woff2',
      weight: '700',
      style: 'normal'
    },
    {
      path: '../public/fonts/Surt-Normal-Semibold-Italic.woff2',
      weight: '600',
      style: 'italic'
    }
  ],
  variable: '--font-surt' // 统一的CSS变量名
});

export default function RootLayout({ children }) {
  return (
    <html lang="zh-CN" className={`${surt.variable} font-sans`}>
      <body>{children}</body>
    </html>
  );
}

重要提醒

必须同时设置变量 ${surt.variable} 和基础类 font-sans

使用 pages/ 目录(传统方式)

pages/_app.js 中:

jsx
import localFont from 'next/font/local';

const surt = localFont({ 
  /* 同上配置 */ 
});

export default function MyApp({ Component, pageProps }) {
  return (
    <main className={`${surt.variable} font-sans`}>
      <Component {...pageProps} />
    </main>
  );
}

步骤2: 配置 Tailwind CSS

更新 tailwind.config.js

js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './src/**/*.{js,ts,jsx,tsx}',
  ],
  theme: {
    extend: {
      fontFamily: {
        sans: ['var(--font-surt)', 'sans-serif']
      },
    },
  },
  plugins: [],
};

步骤3: 在组件中使用

jsx
export default function AboutPage() {
  return (
    <div>
      {/* 使用常规字体 */}
      <p className="font-sans">常规文本</p>
      
      {/* 使用粗体 */}
      <h1 className="font-sans font-bold">标题文本</h1>
      
      {/* 使用斜体 */}
      <blockquote className="font-sans italic">引用内容</blockquote>
    </div>
  );
}

关键实现机制

  1. 字体优化机制

    • Next.js 自动生成 @font-face 规则
    • 字体文件被预加载,消除布局偏移
    • 支持字体显示策略(display: swap 默认开启)
  2. CSS变量集成

    css
    :root {
      --font-surt: 'Surt__Subset';
    }
    
    .font-sans {
      font-family: var(--font-surt), ui-sans-serif, sans-serif;
    }
  3. 多字重处理逻辑

    js
    src: [
      { path: '...', weight: '400', style: 'normal' },
      { path: '...', weight: '700', style: 'normal' }
    ]

    Next.js 会根据实际使用的字重自动加载对应文件

常见问题解决

问题现象解决方案
字体仍未生效检查 <html><main> 标签是否设置了 className={surt.variable}
控制台报告路径错误确保路径从项目根目录开始计算,使用相对路径 ../public/fonts/...
只有部分字重生效src 数组中确保所有字重/样式组合已定义
字体闪烁 (FOUT)localFont 配置中添加 display: 'swap'

版本兼容性

如果你的项目使用 Next.js v13.1 或更低版本,需安装 @next/font 而非 next/font。从 v13.2 开始该功能已整合至核心包

最佳实践建议

  1. 优先使用 WOFF2 格式

    • 现代浏览器支持更优的压缩比
    • 文件体积比 TTF 小约 30%
  2. 按需加载字重

    js
    // 只加载实际使用的字重
    src: isProduction ? [{ path: '...', weight: '400' }] : [...]
  3. 创建字体工具函数/lib/fonts.js 中:

    js
    export function getSurtFont() {
      return localFont({
        src: [...],
        variable: '--font-surt'
      });
    }

遵循此完整解决方案,你可在 Next.js 13 项目中无缝集成自定义本地字体到 Tailwind CSS,同时享受 Next.js 的字体优化优势。