Skip to main content

CSS @layer 怎么控制优先级?

· 4 min read

CSS @layer 用声明式层级替代了特异性战争——无需 !important 也能精确控级。

  1. 机制先声明的层优先级最低,顺序决定一切
  2. 核心:layer 优先于特异性,子选择器也能覆盖上层
  3. 反转!important 反转层级,重要样式反而走底层
  4. 嵌套:子层用 . 访问,写成 @layer base.forms { }
  5. 场景框架 reset + 业务定制分层
  6. 兼容:2023 起所有现代浏览器原生支持

启动:3 行 @layer

@layer reset, components, utilities;

@layer reset {
button { background: gray; }
}

@layer components {
button { background: blue; }
}

@layer utilities {
button { background: green; }
}

button 最终背景色是 greenutilities 是最后声明的层,覆盖前面所有。

不用 !important,不用堆叠 .btn.btn-primary.active 三层选择器——一行 @layer 声明搞定。

核心机制:声明顺序 = 优先级

@layer a, b, c; 三个名字按从左到右声明。先声明的层优先级最低,后声明的覆盖前面——跟普通 CSS "后来的赢" 一回事,但作用在 layer 维度。

layer 优先于 specificity

这才是 @layer 的真正卖点:层之间的优先级高于选择器特异性。

@layer base, theme;

@layer base {
* { color: red; } /* 通配符,特异性 0,0,0,0 */
}

@layer theme {
.btn { color: blue; } /* 类选择器,特异性 0,0,1,0 */
}

最终 colorbluebase 层的通配符被 theme 层的 .btn 覆盖——尽管特异性更低。

这意味着:可以放心把"全局 reset / 工具类"丢进低优先级层,业务代码写高优先级层,特异性不再重要

!important 的反转陷阱

!important 翻转优先级——layer 维度也反转:

@layer base, theme;

@layer base {
button { background: red !important; }
}

@layer theme {
button { background: blue !important; }
}

最终 background 是 red——base 层的 !important 反而赢(layer 顺序反过来)。

关键提醒

!important + @layer 的反转是规范明确定义的,不是 bug。设计分层时要么彻底不用 !important,要么明确知道反转会破坏预期优先级。

嵌套层

层里能套层,用 . 访问:

@layer framework {
@layer reset, components;

@layer reset { }
@layer components { }
}

/* 外部引用 */
@layer framework.reset { }
@layer framework.components { }

匿名层@layer { } 没名字)优先级 = 0(最低),命名层总能覆盖它:

@layer {
button { background: pink; } /* 永远被命名层覆盖 */
}

适合"框架默认 + 用户覆盖"场景——用户一行 @layer user; 就赢。

实战:3 个分层场景

场景 1:Tailwind / Bootstrap + 自定义代码

@layer vendor, app;

@import "tailwindcss";

@layer app {
.my-button { background: hotpink; } /* 总能覆盖 Tailwind */
}

Tailwind v4 / Bootstrap 5 都支持把整个框架塞进低优先级层,业务代码天然胜出。

场景 2:设计系统 token + 业务组件

@layer tokens, components, overrides;

@layer tokens {
:root { --color-brand: #06bdfa; }
}

@layer components {
.btn { background: var(--color-brand); }
}

@layer overrides {
.btn--danger { background: red; }
}

设计师改 token,开发写 components,特殊需求写 overrides——三层分工清晰。

场景 3:第三方 widget 不污染全局

@layer vendor, app;

@layer vendor {
.video-call-popup { /* 三方 CSS,没法改 */ }
}

@layer app {
/* 我们的样式天然比三方优先级高 */
}

如果用 iframe 隔离太重,CSS layer 就是零成本的层级隔离方案。

什么时候用

经验

大型项目(设计系统、微前端、多人协作、第三方 widget)用 @layer 收益最大。小项目三层以下的话,传统特异性管理就够了——layer 引入了额外的心智负担。

References

  1. MDN @layer —— 完整规范参考
  2. CSS Cascade 5 Specification —— W3C 规范源
  3. Tailwind v4 CSS-first config —— Tailwind v4 的 @import "..." 集成方式