KAIROS.WORKSPACE
技术宇宙 / ONLINE
返回文章列表
前端工程intermediate8 分钟

CSS 级联层实战:为什么 @layer 能救回你的工具类

用 @layer 调停基础样式与工具类的优先级之争:未分层规则为何总是赢家,如何用 base 层修正级联,以及哪些规则应该留在层外。

#CSS#级联层#设计系统
排版
字号
行宽
目录 · 6 节

本文为通用技术教程,示例均可在现代浏览器中直接复现。

一个诡异的 Bug

假设站点里有这样一条再普通不过的基础样式:

a {
  color: inherit;
  text-decoration: none;
}

然后给某个链接加一个 Tailwind 工具类换色:

<a href="/subscribe" class="text-[var(--ink-100)]">订阅</a>

预期是文字变成亮色,实际却纹丝不动——工具类“失效”了。检查特异性?类选择器(0,1,0)明明高于元素选择器(0,0,1)。检查源码顺序?把工具类挪到最后也没用。

问题不在特异性,也不在顺序,而在级联层

级联层规则:未分层即最高优先

CSS Cascade Layers 的裁定顺序是:先比较“有没有层”,再比较特异性。

  • 所有 @layer 内的样式,彼此之间按层顺序裁定;
  • 未分层的作者样式,无条件赢过任何层里的样式——无论特异性多低。

Tailwind v4 把工具类输出在 @layer utilities 中。于是:

@layer utilities {
  .text-brand {
    color: var(--brand);
  } /* 层内 */
}

a {
  color: inherit;
} /* 层外 */

层外的 a 直接胜出。这解释了开头的 Bug:不是工具类没生成,而是它在层里“天生低人一等”。

顺带一提,这个规则还会让 hover: 变体悄悄失灵——a:hover { color: … } 若写在层外,即使特异性只有 (0,1,1) 也能压过层内的任何工具类。

修复:把元素级默认样式放进 base 层

Tailwind v4 在样式表开头声明了层顺序:

@layer theme, base, components, utilities;

只要把自己的元素级默认样式放进同名 base 层, utilities 就会按声明顺序正确地覆盖它:

@layer base {
  html {
    background: rgb(var(--bg));
  }
  body {
    color: rgb(var(--text));
    font-family: var(--font-sans);
  }
  a {
    color: inherit;
    text-decoration: none;
  }
  :focus-visible {
    outline: 2px solid rgb(var(--accent));
  }
}

修复后的裁定顺序变成:

  1. 浏览器默认(user agent);
  2. base 层的元素默认;
  3. utilities 层的工具类——赢家。

反过来:哪些规则应该留在层外

层外规则是“终极王牌”,要克制地使用。适合留在层外的只有两类:

  1. Token 定义:root { --accent-primary: … } 和主题覆盖 html[data-accent='…']。它们是整套样式的地基,必须稳赢任何组件层的意外干扰。
  2. 刻意的兜底/重置:确信要压过一切工具类的历史包袱修复,配上注释说明原因。

一个判断标准:这条规则如果被某个工具类覆盖,是“坏了”还是“对了”?答案是“对了”,就该进层。

排查工具

遇到“类写了却不生效”,按这个顺序查:

  1. DevTools 的 Styles 面板:看规则是否出现。出现了但被划掉,看划掉它的规则来自哪一层(面板会标注 layer)。
  2. 控制台验证匹配:document.querySelector(sel).matches('.text-\\[var\\(--x\\)\\]')
  3. 检查层归属:getComputedStyle 不显示层级,最直观的方式是在 Styles 面板看每条规则旁边的 layer 徽标。

小结

级联层把“谁赢”从特异性博弈简化成了声明顺序:theme → base → components → utilities。基础样式进 base 层,工具类在 utilities 层稳赢;token 留在层外当地基。理解这一条,整个设计系统的层叠就再也不靠运气。

Conversation

评论与互动

正在加载评论…

提交后需审核,不会立即公开。

Keep exploring

继续探索