直接用@apply封装到全局css文件里是最轻量、最可控的解法;必须放在@layer components中,且不能在组件style块中使用,因jit引擎不扫描运行时注入的scoped样式。

直接用 @apply 封装到全局 CSS 文件里是最轻量、最可控的解法;但凡写进 Vue/React 组件的 <style></style> 块里,基本就失效了。
@apply 必须放在 @layer components 里,且不能在组件 style 块中使用
Tailwind 的 JIT 引擎只扫描 content 配置里声明的文件路径(如 src/**/*.{vue,js,ts}),而单文件组件里的 <style scoped></style> 是运行时注入的字符串,根本不会被解析——所以以下写法无效:
.my-btn { @apply bg-red-500 text-white px-3 py-1; }
正确做法是:在项目入口 CSS 文件(如 src/styles/tailwind.css)中,用 @layer components 包裹:
@layer components {
.btn {
@apply px-4 py-2 font-medium rounded-lg transition-colors;
}
.btn-primary {
@apply bg-blue-600 text-white hover:bg-blue-700 focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50;
}
}
- 必须用
@layer components,否则 PurgeCSS 构建时会清掉这些类 - 不能嵌套伪类以外的复杂选择器(比如
.btn:hover .icon不支持) -
@apply不接受动态值(@apply {{ dynamicClass }}会报错) - 仅当同一组类高频复用(≥3 次)才值得封装,否则直接写实用类更清晰
需要变体(variant/size/disabled)时,用 tailwind-variants
按钮、输入框这类有多个状态开关的组件,@apply 无法条件组合。此时 tailwind-variants 是目前最贴合 Vue/React 开发习惯的方案:
安装后,在 composables/useButton.ts 中定义:
import { tv } from 'tailwind-variants';
const button = tv({
base: 'px-4 py-2 rounded font-medium',
variants: {
variant: {
primary: 'bg-blue-500 text-white hover:bg-blue-600',
secondary: 'bg-gray-200 text-gray-800 hover:bg-gray-300',
},
size: { sm: 'text-sm px-3 py-1', md: 'text-base px-4 py-2' },
disabled: { true: 'opacity-50 cursor-not-allowed' },
},
defaultVariants: { variant: 'primary', size: 'md' },
});
- 返回的
button()函数可直接传入 props,生成带逻辑的 class 字符串 - 支持响应式断点、嵌套变体、defaultVariants 默认值
- 类型安全(TS 友好),编译后仍为静态类名,不影响 PurgeCSS
- 不依赖框架渲染逻辑,纯函数式,可跨 React/Vue/Svelte 复用
Vue 组件内直接写实用类,比抽象 CSS 类更推荐
多数情况下,与其费劲抽 @apply 类,不如在 Vue 模板里直接写 Tailwind 类,并用 v-bind:class 控制条件样式:
<button :class="[
'px-4 py-2 rounded font-medium transition-colors',
props.variant === 'primary' && 'bg-blue-600 text-white hover:bg-blue-700',
props.size === 'sm' && 'text-sm px-3 py-1',
props.disabled && 'opacity-50 cursor-not-allowed'
]">
{{ props.children }}
</button>
- 无构建依赖,开发时实时生效
- 避免 CSS 类名语义污染(比如
.btn-primary在不同上下文可能含义冲突) - 调试直观:DOM 上直接看到最终 class,不用跳转查
@layer - 配合 VS Code 插件(如 Tailwind CSS IntelliSense),补全和 lint 支持完善
真正容易被忽略的是:Tailwind 的“可复用”本质是“结构+类名”的组合复用,不是 CSS 类的复用。抽得太早或太深,反而增加心智负担和维护成本;先写透、再提炼,比一开始就想封装更可靠。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











