如果一个实用程序类只做一件事,那么您可能不希望它被来自其他地方的任何样式覆盖。一种方法是使用 !important
来 100% 确保样式会被应用,无论特异性冲突如何。
Tailwind 配置文件有一个 !important
选项,它会自动将 !important
添加到每个实用程序类中。以这种方式使用 !important
并没有错,但如今有更好的方法来处理特异性。使用 CSS 级联层,我们可以避免使用 !important
的强硬方法。
级联层允许我们将样式分组到“层”中。层的优先级始终高于选择器的特异性。特异性只在每个层内起作用。建立合理的层级顺序有助于避免样式冲突和特异性冲突。这就是使 CSS 级联层成为管理自定义样式以及来自第三方框架(如 Tailwind)的样式的绝佳工具的原因。 管理自定义样式以及来自第三方框架的样式
Tailwind 源 .css
文件通常以类似这样的方式开始
@tailwind base;
@tailwind components;
@tailwind utilities;
@tailwind variants;
让我们看看关于指令的 官方 Tailwind 文档
指令是在您的 CSS 中可以使用的一些自定义 Tailwind 特定的 at-规则,它们为 Tailwind CSS 项目提供特殊的功能。使用
@tailwind
指令将 Tailwind 的base
、components
、utilities
和variants
样式插入到您的 CSS 中。
在生成的 CSS 文件中,Tailwind 的 CSS 重置(称为 Preflight)作为基础样式的一部分首先包含在内。其余的 base
包含 Tailwind 工作所需的 CSS 变量。components
是您添加自己的自定义类的地方。您在标记中使用的任何实用程序类都会接下来出现。变体是针对悬停和焦点状态以及响应式样式的样式,它们将最后出现在生成的 CSS 文件中。
@layer
指令
Tailwind 的 令人困惑的是,Tailwind 有自己的 @layer
语法。本文讨论的是 CSS 标准,但让我们快速了解一下 Tailwind 版本(它会被编译掉,不会出现在输出 CSS 中)。Tailwind 的 @layer
指令是一种将您自己的额外样式注入到输出 CSS 文件的指定部分的方法。
例如,要将您自己的样式追加到 base
样式,您可以执行以下操作
@layer base {
h1 {
font-size: 30px;
}
}
默认情况下,components
层是空的——它只是一个放置您自己的类的地方。如果您以 Tailwind 的方式做事,您可能会使用 @apply
(尽管 Tailwind 的创建者最近 建议不要这样做),但您也可以以常规方式编写类
@layer components {
.btn-blue {
background-color: blue;
color: white;
}
}
CSS 标准功能更强大。让我们回到那个话题……
@layer
使用 CSS 标准 以下是如何重写此代码以使用 CSS 标准 @layer
@layer tailwind-base, my-custom-styles, tailwind-utilities;
@layer tailwind-base {
@tailwind base;
}
@layer tailwind-utilities {
@tailwind utilities;
@tailwind variants;
}
与 Tailwind 指令不同,这些指令不会被编译掉。浏览器可以理解它们。事实上,Edge、Chrome、Safari 和 Firefox 中的开发者工具甚至会显示您定义的任何层。

您可以拥有任意数量的层——并为它们命名您想要的任何名称——但在本例中,我的所有自定义样式都在一个层(my-custom-styles
)中。第一行建立了层级顺序
@layer tailwind-base, my-custom-styles, tailwind-utilities;
这需要提前提供。请确保在任何其他使用 @layer
的代码之前包含此行。列表中的第一个层将是最不强大的,而列表中的最后一个层将是最强大的。这意味着 tailwind-base
是最不强大的层,其中任何代码都将被所有后续层覆盖。这也意味着 tailwind-utilities
将始终胜过任何其他样式——无论源顺序或特异性如何。(实用程序和变体*可以*位于单独的层中,但 Tailwind 的维护人员将确保变体始终胜过实用程序,只要您将变体包含在实用程序指令下方即可。)
任何不在层中的内容都将覆盖任何在层中的内容(使用 !important
的样式除外)。因此,您也可以选择将 utilities
和 variants
保留在任何层之外
@layer tailwind-base, tailwind-components, my-custom-styles;
@layer tailwind-base {
@tailwind base;
}
@layer tailwind-components {
@tailwind components;
}
@tailwind utilities;
@tailwind variants;
这实际上给我们带来了什么?在很多时候,高级 CSS 选择器非常有用。让我们创建一个仅响应键盘焦点而不是鼠标点击的 :focus-within
版本,使用 :has
选择器(它在 Chrome 105 中可用)。当其任何子元素获得焦点时,这将为父元素设置样式。Tailwind 3.1 引入了 自定义变体——例如 <div class="[&:has(:focus-visible)]:outline-red-600">
——但有时直接编写 CSS 更容易
@layer tailwind-base, my-custom-styles;
@layer tailwind-base {
@tailwind base;
}
@tailwind utilities;
@layer my-custom-styles {
.radio-container {
padding: 4px 24px;
border: solid 2px rgb(230, 230, 230);
}
.radio-container:has(:focus-visible) {
outline: solid 2px blue;
}
}
假设在一个实例中,我们希望将 outline-color
从 blue
覆盖为其他颜色。假设我们正在处理的元素同时具有 Tailwind 类 .outline-red-600
和我们自己的 .radio-container:has(:focus-visible)
类
<div class="outline-red-600 radio-container"> ... </div>
哪个 outline-color
会获胜?
通常,.radio-container:has(:focus-visible)
较高的特异性意味着 Tailwind 类无效——即使它在源顺序中较低。但是,与依赖于源顺序的 Tailwind @layer
指令不同,CSS 标准 @layer
覆盖了特异性。
因此,我们可以在自己的自定义样式中使用复杂的选择器,但仍然可以在需要时用 Tailwind 的实用程序类覆盖它们——而无需诉诸强硬的 !important
使用来获得我们想要的结果。
还需要注意的是,使用级联层时,不应将
!important
用作覆盖特异性的措施。如 本文(也在上面的文章中链接)中所述,对于
!important
规则,层的优先级是反向的,允许较低优先级的层真正将某些规则标记为过于重要,以至于无法被后续层覆盖(即使它们有自己的!important
规则)。这种行为要求您谨慎使用!important
。它在我的 Vite 和 React 项目中不起作用(我收到一条消息,提示 Tailwind 不支持嵌套规则)。