Tailwind动画类在生产环境失效的根本原因是JIT编译器仅扫描源码中明确写出的字面量类名(如animate-spin),不解析JS运行时拼接的字符串;必须确保content配置覆盖所有含动画类的文件路径(包括.tsx/.jsx及App Router的/app/**目录)、静态HTML、含空格路径需加引号,并为动态类添加safelist(支持硬编码或正则,需包含响应式前缀);自定义动画、@apply用法及第三方库的动画类路径也须纳入content扫描范围。

动画类在生产环境失效,基本就是 content 没扫到你写动画的地方——Tailwind 不执行 JS,不解析运行时拼的字符串,只认源码里明明白白写着的 animate-bounce、animate-pulse 这种完整字面量。
检查 content 是否覆盖所有含动画类的文件路径
动画类(如 animate-spin、animate-fade-in)和其他工具类一样,必须出现在 content 显式声明的文件中,才会被提取进最终 CSS。漏掉一个文件类型或目录,对应动画就直接消失。
-
./src/**/*.{js,ts}会漏掉所有.tsx和.jsx文件,React 组件里的animate-ping就不会生成 - Next.js App Router 项目必须包含
./app/**/*.{js,ts,jsx,tsx},否则layout.tsx或page.tsx中的animate-bounce会被 PurgeCSS 清空 - 静态 HTML 模板(如
public/index.html)没加进content,里面硬写的class="animate-spin"同样被删 - 路径含空格或中文时,CLI 构建命令中
--content值没用双引号包裹,该路径实际未生效
动态拼接的动画类必须进 safelist
JSX 中 className={`animate-${type}`} 或 class="animate-${status}" 这类写法,源码里根本没出现过 animate-spin 这个字符串,JIT 编译器完全看不到,自然不生成规则。
- 固定枚举可硬编码:
safelist: ['animate-spin', 'animate-pulse', 'animate-bounce'] - 多变体推荐正则:
{ pattern: /animate-(spin|pulse|bounce|ping)/ } - 响应式前缀要显式包含:
/^(md|lg):animate-spin$/,只写animate-spin会漏掉md:animate-spin - 避免
.*结尾:/animate-.*/可能误匹配原生 CSS 属性animation-play-state,引入冗余
确认是否用了自定义动画或第三方插件
如果你在 tailwind.config.js 里扩展了 animation 或 keyframes,或者用了 @apply animate-custom,这些类名也得被 content 扫到,否则连基础定义都进不了 CSS。
立即学习“前端免费学习笔记(深入)”;
-
@apply animate-spin必须放在@layer utilities或@layer components内,且该文件本身要被content包含 - 自定义 keyframes 定义在
src/styles/keyframes.css?那路径必须加进content,否则animate-custom规则为空 - DaisyUI、Flowbite 等库内部用了
animate-*类?它们的源码路径(如node_modules/daisyui/src/components/tooltip.css)也得列进content,否则全清空
最容易被忽略的是:动画类一旦动态拼接,就彻底脱离 JIT 的扫描能力——没有 safelist,就没有 CSS 规则;而 safelist 写错正则边界或漏响应式前缀,等于白加。


















