You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在TailwindCSS+Next.js项目中集成Next.js字体变量到Storybook

让Next.js自定义字体在Storybook中正常生效的方案

核心问题原因

Storybook是独立于Next.js的运行环境,不会自动执行Next.js RootLayout中的字体注入逻辑,所以next/font生成的CSS变量不会被添加到body上,导致Tailwind配置的字体族无法生效。

方案一:复用Next/Font逻辑,在Storybook装饰器中注入变量

直接把Next.js里的字体配置搬到Storybook的预览入口,通过装饰器把变量类名加到body上:

  1. 修改.storybook/preview.tsx(如果是JS环境就用preview.js):
import { Alata, DM_Serif_Display, Open_Sans } from 'next/font/google';
import { useEffect } from 'react';

// 完全复用你在RootLayout里的字体配置
const alata = Alata({
  weight: '400',
  subsets: ['latin'],
  variable: '--font-alata'
});
const openSans = Open_Sans({
  variable: '--font-open-sans',
  subsets: ['latin-ext']
});
const dmSerif = DM_Serif_Display({
  weight: '400',
  variable: '--font-dm-serif',
  subsets: ['latin-ext']
});

// 全局装饰器,给body添加字体变量类
export const decorators = [
  (Story) => {
    useEffect(() => {
      document.body.classList.add(alata.variable, openSans.variable, dmSerif.variable);
      // 组件卸载时清理类名
      return () => {
        document.body.classList.remove(alata.variable, openSans.variable, dmSerif.variable);
      };
    }, []);
    return <Story />;
  },
];

// 保留你原有的Storybook参数配置
export const parameters = {
  // ...你的现有参数,比如viewport、controls等
};
  1. 确认你的Tailwind配置已经正确关联变量(你当前的配置没问题,无需修改):
// tailwind.config.js
module.exports = {
  extend: {
    fontFamily: {
      sans: ['var(--font-open-sans)', 'sans-serif'],
      alata: ['var(--font-alata)', 'sans-serif'],
      display: ['var(--font-dm-serif)', 'sans-serif'],
    },
  },
};

方案二:用全局CSS手动加载字体(更轻量化)

如果不想依赖next/font的逻辑,可以直接通过Google Fonts的CDN链接加载字体,并手动定义CSS变量:

  1. 创建.storybook/globals.css:
/* 注意:这里的字体URL要和你用next/font加载的权重、子集一致 */
@import url('https://fonts.googleapis.com/css2?family=Alata&family=DM+Serif+Display&family=Open+Sans:wght@400;500;600&display=swap');

:root {
  --font-alata: 'Alata', sans-serif;
  --font-open-sans: 'Open Sans', sans-serif;
  --font-dm-serif: 'DM Serif Display', sans-serif;
}
  1. 在.storybook/preview.js中引入这个全局样式:
import './globals.css';

// 其他装饰器或参数配置
export const decorators = [
  (Story) => <Story />,
];

验证方法

运行Storybook后,打开浏览器开发者工具:

  • 检查body元素的class列表,是否包含next-font-xxx类(方案一)
  • 查看:root或body的CSS变量,确认--font-xxx已正确定义
  • 检查使用字体的元素,计算样式中的font-family是否包含你的自定义字体

内容的提问来源于stack exchange,提问作者Tomasz Bawor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 04:57:39