你以为 CSS 优先级只能靠越写越长的 class 名?今天 @layer 把这件事彻底原生化了
写 CSS 的人都踩过这个坑——组件样式被第三方框架覆盖时,第一反应是「那我再加个 class」或者直接上 !important。结果呢?选择器越来越长,!important 越写越多,到最后连自己都分不清哪条规则在起作用。
这其实不是你的问题,是 CSS 级联(cascade)机制在没有 @layer 之前,根本没有提供任何控制优先级的原生手段。
@layer 是什么
@layer 是 CSS Cascade Layers 规范的核心规则,本质上是在浏览器内部建立一套命名空间,让不同来源的样式天然就有优先级高低之分。
语法非常直观:
/* 先声明层级顺序,越后面的层优先级越高 */
@layer reset, base, components, utilities;
/* 随便在哪写样式都行,层顺序说了算 */
@layer reset {
* { margin: 0; padding: 0; box-sizing: border-box; }
}
@layer base {
body { font-family: system-ui; }
}
@layer components {
.card { border: 1px solid #ddd; }
}
@layer utilities {
.text-center { text-align: center; }
}
这里 .card 的选择器虽然简单,但只要它落在 components 层,优先级就天然高于 reset 和 base 层的任何样式——不需要更高权重的选择器,不需要 !important。
和框架共存时才是真正发挥价值的地方
引入 Bootstrap 或 Tailwind 之类的框架,最烦的不是配置,是「我想改一个按钮样式,但框架的 class 更强,怎么都覆盖不掉」。用 @layer 只需要一行:
/* 声明层顺序,框架在低优先级,你写的在高的 */
@layer bootstrap, custom;
@import url('bootstrap.css') layer(bootstrap);
@layer custom {
.btn-primary {
background-color: #1a73e8;
padding: 12px 24px;
}
}
Tailwind 那边也是同理——它内部本身就用了 @layer base/components/utilities 的结构,导入时给它包一层 layer(tailwind) 就能无缝融入你自己的层级体系。
一个反直觉的坑:!important 在 @layer 里的行为是反的
正常 CSS 里 !important 让样式权重变大。但在 @layer 里它反过来——低优先级层的 !important 会赢过高优先级层的普通声明:
@layer low {
button { color: blue !important; }
}
@layer high {
button { color: red; }
}
/* 实际颜色是 blue,因为 low 层的 !important 反转了优先级 */
这个设计是有道理的:让你在基础层(比如无障碍相关样式)用 !important 确保关键样式不被框架覆盖,同时不会污染整个代码库。但用的时候一定要心里有数。
浏览器支持
截至 2026 年,Chrome、Firefox、Safari、Edge 全部支持,Baseline 2022,几乎没有兼容问题。
下一步
如果你的项目还没用过 @layer,建议从这三个场景开始:
- CSS Reset:把
normalize.css或reset.css放最底层,后面的组件层天然覆盖它,不会干扰框架 - 第三方框架覆盖:用
@import "bootstrap.css" layer(framework)包裹,定制样式写在自己层里,稳赢 - 设计系统:把基础变量、组件、工具类分层,团队里没人需要再靠
!important或超长选择器来抢优先级了
说到底,@layer 解决的是一个长期被前端社区用「最佳实践」(BEM、更长的选择器)硬扛的问题——浏览器终于原生提供了答案。
评论区
登录后可评论。