应使用 @layer components 定义基础语义类,响应式和变体类必须写在 html 的 class 属性中;高频动态组件推荐用 tailwind-variants;避免在 @layer 中混用变体,确保 jit 正确生成规则。

用 @layer components 替代 @apply 处理响应式和变体组合
直接写 @apply md:p-4 hover:bg-gray-100 dark:hover:bg-gray-800 很容易失效——md: 和 dark:hover: 在 PostCSS 静态展开阶段被丢弃,编译后只剩普通声明。这不是你漏写了,是 @apply 本身不处理嵌套变体逻辑。
正确做法是把语义化类名(比如 .card)放进 @layer components,然后在 HTML 中直接写原子类:
@layer components {
.card {
@apply p-4 rounded-lg bg-white shadow-sm;
}
}
但注意:上面这个写法依然有风险。真正安全的是只声明类名,不带任何变体:
-
@layer components块里只放基础样式,如.avatar、.btn - 所有
hover:、md:、dark:等变体,必须写在 HTML 的 class 属性里 - 这样 JIT 引擎才能扫描到并生成对应规则,包括交叉状态(如
dark:hover:bg-gray-800)
高频动态组件优先用 tailwind-variants
当一个按钮要根据 variant、size、disabled 切换样式时,硬编码类名或 @apply 会迅速失控。比如:
button({ variant: 'primary', size: 'lg', disabled: true })
返回的字符串是合法原子类组合:px-6 py-3 text-lg bg-blue-600 text-white opacity-50 cursor-not-allowed,完全兼容 PurgeCSS 和 JIT。
关键点:
-
tailwind-variants是运行时逻辑,不是 CSS 抽象,不会影响构建产物 - 它自动支持响应式前缀(
md:px-8)、暗色模式(dark:bg-gray-900)、条件组合(disabled:opacity-50) - TypeScript 类型推导能帮你提前发现无效的
variant值
别把“复用”等同于“抽成一个 CSS 类”
Tailwind 的原子性优势在于可拆解。md:p-4 和 p-2 本就该独立存在,强行合并成 .card-padding 反而锁死定制能力。所谓“复用”,本质是控制抽象层级:
- 静态结构(如卡片边框+圆角+阴影)→ 用
@layer components定义语义类,HTML 里仍保留变体 - 动态逻辑(如按钮颜色/尺寸/状态组合)→ 交给
tailwind-variants或组件 props 处理 - 其余场景,直接写原子类反而最快,也最可控
最容易被忽略的是:你在 .vue 或 .tsx 文件里写的 @apply,如果用了 scoped 或没被 Tailwind 扫描到 content 路径,根本不会生成 CSS 规则——连报错都没有,只是样式不出现。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











