需在.storybook/preview.js中导入PostCSS编译后的Tailwind CSS文件,并在.main.js中配置postcss-loader、确保tailwind.config.js的content包含Storybook路径且以./开头,同时避免动态类名插值。

直接在 preview.js 中 import 编译后的 Tailwind CSS 文件即可预览,但前提是 Webpack 构建链必须正确接管 @apply、响应式类和动态类名——否则你看到的只是“样式缺失”或“类名不生效”,不是 Storybook 问题,而是 Tailwind 的构建上下文没对齐。
为什么 preview.js 里 import index.css 仍不生效?
多数人卡在这一步:以为只要 @tailwind base 写在 src/index.css 里,再 import '../src/index.css' 就完事。实际失效主因有三个:
- 路径错误:从
.storybook/目录出发,应写../src/index.css,而非./src/index.css或src/index.css - 文件未编译:
index.css含@tailwind指令,浏览器无法解析,必须由 PostCSS 处理后输出纯 CSS(如dist/tailwind.css)再 import - PostCSS 链路断开:Storybook 默认不运行
postcss-loader,@apply和@layer会被原样保留,最终生成空规则
如何让 @apply 和响应式类(如 md:flex)正常工作?
必须显式配置 Webpack,把 postcss-loader 插入 SCSS/CSS 处理流程,并确保它能读到 tailwind.config.js:
- 在
.storybook/main.js的webpackFinal中,找到css-loader前的sass-loader或style-loader规则 - 往
use数组中插入{ loader: 'postcss-loader', options: { postcssOptions: { config: path.resolve(__dirname, '../postcss.config.cjs') } } } - 确认
postcss.config.cjs存在且导出tailwindcss插件;若用 CRA 或 Craco,该文件可能被隐藏,需手动创建 -
tailwind.config.js的content必须包含 Storybook 文件路径:"./storybook/**/*.{js,ts,jsx,tsx}",否则md:flex这类类名不会被 JIT 扫描生成
动态类名(如 class={`text-${size}-lg`})为何全失效?
Tailwind 的 JIT 是静态扫描器,它不执行 JS 模板字符串,只认字面量。你在 .stories.tsx 里写 class={`text-${size}-lg`},构建时看到的永远是 text-${size}-lg,不是 text-sm-lg 或 text-md-lg。
立即学习“前端免费学习笔记(深入)”;
- 临时验证:把变量展开成固定类名,比如
class="text-sm-lg text-md-lg",如果这时生效,就坐实是动态类名问题 - 长期方案:改用
clsx+ 白名单,例如const sizes = ['sm', 'md', 'lg']; clsx(sizes.map(s => `text-${s}-lg`)) - 更安全的做法:在 Story 中避免插值类名,改用 ArgTypes 控制固定选项(如
size: { control: { type: 'radio', options: ['sm', 'md', 'lg'] } }),再由组件内部映射为安全类名
最容易被忽略的一点:Tailwind 的 content 路径必须以 ./ 开头,且重启 Storybook 才生效——热重载不会触发 JIT 重新扫描。一旦改了 tailwind.config.js 或新增了故事文件,不重启,md:hidden 这类类名就永远是空白的。



















