6月20日 19:19

TailwindCSS @apply 怎么用?哪些场景不该用?

TailwindCSS 的 @apply 用来把已有的工具类写进 CSS 选择器里。它适合抽取少量重复样式,比如按钮、表单控件、第三方组件覆盖;但不适合把所有 Tailwind 工具类都“搬回 CSS”。如果大量使用 @apply,最后很容易写成一套披着 Tailwind 外衣的传统 CSS,还会带来样式膨胀、优先级混乱和维护成本。

@apply 是什么?

一句话:@apply 可以在 CSS 中复用 Tailwind 工具类。

css
.btn-primary { @apply rounded-md bg-blue-600 px-4 py-2 font-medium text-white; }

然后在 HTML 或组件里使用:

html
<button class="btn-primary">保存</button>

编译后,.btn-primary 会得到这些工具类对应的 CSS 声明。这样写的好处是减少重复,尤其是多个地方都要用同一组样式时,不必每次都写一长串 class。不过 Tailwind 的主要使用方式仍然是直接在模板里写工具类,@apply 是补充手段,不是默认写法。

应该配合 @layer 使用

自定义样式最好放进 Tailwind 的 layer 里,便于控制输出顺序和级联关系。

css
@layer base { body { @apply bg-white text-gray-900 antialiased; } a { @apply text-blue-600 underline-offset-4 hover:underline; } } @layer components { .btn { @apply inline-flex items-center justify-center rounded-md px-4 py-2 text-sm font-medium transition-colors; } .btn-primary { @apply bg-blue-600 text-white; } .btn-secondary { @apply border border-gray-300 bg-white text-gray-900; } }

base 适合写全局基础标签样式,影响面大,别写太重。components 最适合按钮、表单、卡片、导航项这类重复出现、语义稳定的组件。少量项目级工具类可以放在 utilities,Tailwind v4 里如果要注册真正的工具类,更推荐用 @utility

适合用 @apply 的场景

按钮、表单控件、卡片和第三方组件覆盖,是比较适合 @apply 的场景。

css
@layer components { .form-input { @apply w-full rounded-md border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 outline-none; } .panel { @apply rounded-xl border border-gray-200 bg-white p-6 shadow-sm; } }

第三方库生成的 DOM 不一定方便直接加 Tailwind class,这时 @apply 很实用:

css
.select2-dropdown { @apply rounded-lg border border-gray-200 shadow-lg; } .select2-search input { @apply rounded-md border-gray-300 text-sm; }

hover、focus、响应式有什么限制?

很多人会尝试这样写:

css
.btn-primary { @apply bg-blue-600 hover:bg-blue-700; }

在不同 Tailwind 版本和构建环境里,这类写法可能遇到限制。更稳的方式是把状态拆成普通 CSS 选择器,或者在 Tailwind v4 中使用 @variant

css
@layer components { .btn-primary { @apply bg-blue-600 text-white; } .btn-primary:hover { @apply bg-blue-700; } .btn-primary:focus-visible { @apply outline-none ring-2 ring-blue-500 ring-offset-2; } }

Tailwind v4 可以这样写:

css
.btn-primary { @apply bg-blue-600 text-white; @variant hover { @apply bg-blue-700; } }

响应式如果只是某个元素在不同断点变化,直接在模板里写 md:lg: 更直观。不要为了“HTML 看起来短一点”把所有响应式逻辑藏进 CSS。

CSS 变量可以和 @apply 一起用

复杂一点的组件,可以把稳定部分交给 @apply,动态值交给 CSS 变量。

css
@layer components { .badge { --badge-bg: theme(colors.gray.100); --badge-color: theme(colors.gray.700); @apply inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium; background-color: var(--badge-bg); color: var(--badge-color); } .badge-success { --badge-bg: theme(colors.green.100); --badge-color: theme(colors.green.700); } }

在 Tailwind v4 里,项目配置更偏 CSS-first,可以直接使用主题变量,例如 var(--color-green-700)。设计 token 尽量从 Tailwind 体系来,别在组件 CSS 里散落一堆魔法值。

什么时候用 @apply,什么时候直接写工具类?

场景建议
只出现一次的样式直接写 Tailwind 工具类
重复出现 3 次以上的稳定样式组合可以考虑 @apply
按钮、表单、卡片这类基础组件适合 @apply 或组件封装
状态和变体很多的 UI优先用组件 props 管理 class
第三方组件 DOM 不好加 class适合用 @apply 覆盖
需要支持 hover:lg: 等变体的自定义工具Tailwind v4 优先用 @utility

如果项目已经有 React、Vue 组件系统,很多时候不需要用 @apply 抽类名,而是直接封装组件,用 props 管理 variant、size、disabled、loading 等状态。

常见坑

@apply 不是 Sass mixin,不适合层层套娃;不要把自定义组件类再 apply 到另一个组件类里。过早抽象也会导致后面每个地方都要覆盖,最后 CSS 比原来更乱。

@apply 会把工具类对应的声明内联到你的选择器中。多个组件重复 @apply 同一批工具类,就可能生成重复 CSS。少量没问题,大量抽象会让 CSS 变厚。

@apply 时尽量保持选择器简单。如果写出 .page .card .title 这类复杂选择器,覆盖关系会变得难读。

Tailwind v4 更强调 CSS-first:写组件类可以继续用 @layer components + @apply;写真正的工具类更推荐 @utility;写 hover、dark、focus 等变体优先考虑 @variant 或普通伪类。@apply 可以用,但要克制。

标签:Tailwind CSS