tailwind css 样式不生效主因是 jit 未启用或热更新链路中断,需确认终端输出“using jit (just-in-time) mode”、content 路径正确、无动态 classname 拼接、postcss 插件顺序合规,且配置修改后必须重启服务。

Tailwind CSS 样式改了但页面没反应,基本就是 JIT 没真跑起来,或者热更新链路被绕过了——不是代码写错了,而是构建信号断了。
确认终端是否打印 Using JIT (Just-In-Time) mode
这是唯一硬指标。没有这行,说明 Tailwind 还在用旧流程全量编译,热重载必然卡顿甚至失效。
- 运行
npx tailwindcss -v,输出必须是v3.x.x或v4.x.x;v2或带@tailwindcss/jit包的项目会退化 - Vite 项目启动后,终端第一屏日志里必须出现
Using JIT (Just-In-Time) mode;没这句就等于没启用 JIT - 如果用了自定义脚本(如
npm run dev:tailwind),确保环境变量TAILWIND_MODE=watch显式传入,否则开发模式可能被误判为生产
content 路径漏扫或写错格式
Tailwind JIT 不猜你写了什么 class,它只扫描 content 数组里明确列出的路径。漏一个 .tsx,那个文件里的所有类就彻底不进编译流水线。
-
content必须是数组,不能是字符串:['./src/**/*.{js,jsx,ts,tsx}']✅,'./src/**/*.tsx'❌ - Vue 项目必须包含
.vue:['./src/**/*.{vue,js,ts,jsx,tsx}'] - Next.js 双路由要同时覆盖:
['./app/**/*.{js,ts,jsx,tsx}', './pages/**/*.{js,ts,jsx,tsx}'] - 避免宽泛路径如
./**/*.js,它会扫node_modules和dist,I/O 拖垮监听响应
动态 className 拼接让 JIT 完全失能
JIT 是静态分析器,只认字符串字面量。模板字符串一出现,对应组合类就从生成结果里消失,热更新时既不新增也不更新。
- ❌
className={`text-${size}-500`}→text-sm-500根本不会生成 - ✅ 改用条件判断:
className={size === 'sm' ? 'text-sm-500' : 'text-lg-500'} - ✅ 或用
clsx:className={clsx({ 'text-sm-500': size === 'sm' })} - 高频动态值可加白名单:
safelist: [/text-(sm|lg|xl)-500/],但别滥用,否则体积反弹
Vite / Storybook / Next.js 等环境插件链错位
尤其在 Storybook 或自定义 Webpack 配置中,postcss-loader 如果没插对位置,@apply、响应式变体、暗色模式等都会失效。
- Storybook:检查
.storybook/webpack.config.js中postcss-loader是否在sass-loader之后、css-loader之前,且config.path指向正确的postcss.config.cjs - Next.js:官方建议不要写
postcss.config.js,除非你明确需要定制cssnano;若必须写,确保tailwindcss是第一个插件 - Vite:优先用
@tailwindcss/vite插件,它自动处理注入和扫描,不用手动配 PostCSS - 所有配置变更后,必须重启开发服务器——Tailwind 不热重载自己的配置文件
最常被忽略的是:改完 tailwind.config.js 或 postcss.config.cjs 后没重启服务,以及 content 路径里漏掉 Storybook 的 .stories.ts 或 Vue 的 .vue 后缀——这些地方一漏,热重载就变成“假死”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











