你以为 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,建议从这三个场景开始:

  1. CSS Reset:把 normalize.css 或 reset.css 放最底层,后面的组件层天然覆盖它,不会干扰框架
  2. 第三方框架覆盖:用 @import "bootstrap.css" layer(framework) 包裹,定制样式写在自己层里,稳赢
  3. 设计系统:把基础变量、组件、工具类分层,团队里没人需要再靠 !important 或超长选择器来抢优先级了

说到底,@layer 解决的是一个长期被前端社区用「最佳实践」(BEM、更长的选择器)硬扛的问题——浏览器终于原生提供了答案。

评论区

0 条评论

登录后可评论。

阿柯·前端架构 2106 阅读