Storybook 中 Tailwind 样式失效的根本原因是构建链路未对齐:Webpack 未正确注入 postcss-loader 处理 @apply、tailwind.config.js 的 content 未覆盖 Storybook 文件路径、动态类名因 JIT 静态扫描机制无法解析,且配置修改后必须重启服务而非热重载。

@apply 指令不解析、响应式类(如 md:text-lg)缺失、动态拼接的类名(如 text-${color}-500)完全空白——这些不是 Storybook 的 bug,而是 Tailwind 的构建机制在 Storybook 环境中未被正确触发。
Storybook 的 Webpack 配置没接管 SCSS + PostCSS 流程
你写的 @apply 在 .scss 文件里,但 Storybook 默认只用 sass-loader 编译成 CSS,跳过了 postcss-loader。结果就是 @apply 被当作文本注释原样保留,最终 CSS 里没有对应规则。
- 必须把
postcss-loader显式插入到 SCSS 处理链中,且顺序严格为:sass-loader→postcss-loader→css-loader -
include路径要覆盖src/和storybook/,不能只写./storybook—— 否则组件里的 SCSS 根本不进这条规则 - 确认
.storybook/webpack.config.js中postcss-loader的config.path指向包含postcss.config.cjs的目录(通常是项目根目录或.storybook)
tailwind.config.js 的 content 路径漏掉了 Storybook 文件
Storybook 的故事文件(.stories.ts 或 .stories.vue)里写的 class="md:flex",如果 content 没扫到这些文件,Tailwind JIT 就不会生成 @media (min-width: 768px) { .md\:flex { display: flex; } } 这类规则。
- 检查
tailwind.config.js的content数组是否包含:"./storybook/**/*.{js,ts,jsx,tsx,vue}" - 路径必须以
./开头;写成"storybook/**/*"或"../storybook/**/*"都会被 Tailwind 忽略 - 如果用了自定义 stories 目录(比如
src/stories),也得加进去,不能只依赖默认路径
动态类名(class="text-${size}-lg")在 Storybook 里彻底消失
Tailwind 是静态扫描,它不会执行 JS 模板字符串。你在故事文件里写 class={`text-${size}-lg`},JIT 构建时看到的只是字面量 text-${size}-lg,不是具体值,所以连 text-sm-lg、text-md-lg 都不会生成。
- 临时验证:把变量展开成固定字符串,比如
class="text-sm-lg text-md-lg text-lg-lg",看是否生效 —— 如果生效,就是动态类名问题 - 长期方案:改用
clsx或twMerge配合安全白名单(例如预定义const sizes = ['sm', 'md', 'lg'],再sizes.map(s => `text-${s}-lg`)) - 避免在 Storybook 故事里用带插值的 class 字符串;演示变体时,直接写多个静态 story
重启 Storybook 服务是硬性要求,热重载不生效
修改了 tailwind.config.js、postcss.config.cjs 或 .storybook/webpack.config.js 后,仅刷新浏览器或保存文件毫无作用。Node.js 模块缓存、Webpack 配置缓存、Tailwind 的内部状态全都是进程级的。
立即学习“前端免费学习笔记(深入)”;
- 必须彻底终止进程(
Ctrl+C),再运行npm run storybook(或对应命令) - 如果用了
yarn或pnpm,确保命令一致;混用包管理器会导致 node_modules 缓存错乱 - 首次启动后,留意终端输出是否有
Content files scanned行,并确认列出的文件路径包含你的 stories 和组件


















