@apply 必须放在 @layer components 中,因为 Tailwind JIT 引擎仅在此上下文中识别并展开它,且需位于 @tailwind base 之后、utilities 之前;否则样式不生效、状态/断点丢失、PurgeCSS 误删。

直接用 @layer components 在全局 CSS 文件里定义语义化类,是最稳定、最易维护的方案;写在组件 <style> 块或普通 CSS 规则里基本无效。
为什么 @apply 必须放在 @layer components 里?
Tailwind 的 JIT 引擎只在特定上下文中解析 @apply:它必须出现在 @tailwind base 之后、@tailwind utilities 之前,且仅在 @layer components 块内才被识别和展开。否则会出现样式不生效、hover/focus 断点丢失、PurgeCSS 误删等问题。
-
@layer components必须显式声明,不能省略 - 不能写在
@layer utilities或@layer base中——会被忽略 - 如果用了
content配置(如src/**/*.{js,ts,jsx,tsx}),自定义类名必须出现在扫描路径下的文件中,否则 PurgeCSS 会删掉它
怎么写一个带响应式和状态的按钮类?
所有变体(hover:、disabled:、md:)都支持,但必须写在同一行 @apply 中;多行 @apply 会覆盖前一次,导致部分样式丢失。
- 正确写法:
@apply px-4 py-2 bg-blue-500 hover:bg-blue-600 md:px-6 disabled:opacity-50; - 错误写法:拆成两行
@apply px-4; @apply hover:bg-blue-600; - 命名建议加前缀(如
.btn-primary),避免与未来新增的 utility class 冲突 - 浏览器开发者工具里看到的是展开后的原子类(如
bg-blue-500),不是原始类名——这是预期行为,不是 bug
什么时候该换 tailwind-merge 或 tailwind-variants?
当你开始在 JSX/TSX 中动态拼接 className,比如 className={`${base} ${isActive ? 'bg-blue-500' : 'bg-gray-200'}`}`,说明你已经超出了 @layer components 的适用边界。
立即学习“前端免费学习笔记(深入)”;
-
tailwind-merge解决运行时类名冲突(如同时传入text-red-500和text-blue-500) -
tailwind-variants适合多维正交组合(如variant="outline"+size="sm"+color="green"),但它引入运行时函数调用 - 只有固定几个形态(如
btn-primary、btn-outline、btn-danger)时,@layer components完全够用
真正容易被忽略的点是:类名必须承载语义,而不是样式快照。.btn-primary 不只是“蓝底白字”,它隐含可点击、有焦点反馈、禁用态不可交互——这些约束一旦脱离 HTML 结构或 JS 状态管理,就只剩视觉表象了。


















