@layer components 是唯一可靠位置,自定义复合类须写在全局CSS中且位于@tailwind base后、utilities前;组件内无效;必须包裹@layer、加前缀、单行@apply;推荐theme.extend+CSS变量;高频复用(≥3次)才封装;content路径遗漏将导致类静默不生成。

@layer components 是唯一可靠的位置
所有自定义复合类必须写在全局 CSS 文件中,且严格位于 @tailwind base 之后、@tailwind utilities 之前。Vue/React 单文件组件里的 <style scoped></style> 或运行时注入的样式块,JIT 引擎根本不会扫描——写了也白写,构建后直接消失。
常见翻车点:
- 把
.btn-primary定义在组件<style></style>里,开发时看着正常,上线就没了 - 漏掉
@layer components包裹,PurgeCSS 会当成无用类清掉 - 命名没加前缀(比如直接叫
.primary),未来和 Tailwind 新增的原生类冲突
@apply 必须单行写全所有变体
@apply 不支持多行拼接,也不支持嵌套语法(如 &:hover)。hover、focus、md:、dark: 等状态和响应式前缀,必须显式写在同一行里,否则会被覆盖或忽略。
正确写法示例:
立即学习“前端免费学习笔记(深入)”;
@layer components {
.btn-primary {
@apply px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50 md:px-5 dark:bg-blue-800;
}
}
错误写法(会导致部分样式失效):
.btn-primary {
@apply px-4 py-2;
@apply bg-blue-600 text-white;
@apply hover:bg-blue-700;
}
别硬编码颜色和尺寸,用 theme.extend + CSS 变量
直接写 bg-blue-500 或 text-lg 会让组件失去主题适配能力。深色模式切换、品牌色替换、设计系统升级都会卡死。
推荐做法:
- 在
tailwind.config.js的theme.extend.colors中声明语义化 token:accent: 'var(--color-accent)' - 组件内用
bg-accent、text-accent,再通过:root和.dark设置 CSS 变量值 - 尺寸类如
h-[--size-height]配合style="--size-height: 48px;"替代固定h-12
高频复用才值得封装,否则直接写 utility class
同一组工具类在项目中出现 ≥3 次,再考虑抽成 @layer components 类。否则反而增加维护成本,还容易误改影响全局。
更复杂场景(如按钮有 variant/size/disabled 多维组合)应直接上 tailwind-variants,而不是强行用 @apply 堆砌:
import { tv } from 'tailwind-variants';
const button = tv({
base: 'px-4 py-2 rounded font-medium',
variants: {
variant: { primary: 'bg-accent text-white', outline: 'border border-accent text-accent' },
size: { sm: 'text-sm px-3 py-1', lg: 'text-lg px-6 py-3' },
disabled: { true: 'opacity-50 cursor-not-allowed' }
}
});
这类逻辑无法靠 @apply 表达,硬写只会让 CSS 膨胀、调试困难。
真正容易被忽略的是:哪怕插件或 @layer 写得完全正确,只要 tailwind.config.js 的 content 数组没覆盖到实际使用该类的文件路径(比如漏了 ./src/components/**/*.{vue,ts}),类名就静默不生成——连报错都没有。



















