---
URL: "/zh-CN/blog/2026-07/css-layer.html"
LLMS_URL: "/zh-CN/blog/2026-07/css-layer.md"
lastUpdated: true
commentabled: true
recommended: true
title: "深入CSS层叠的本质"
description: "layer如何优雅地解决样式覆盖与important滥用问题"
date:

pageClass: "blog-page-class"
cover: "/covers/css.svg"
---

咱们做前端的，每天都有不可避免的事情—— *CSS样式覆盖*。

场景你一定不陌生：项目越来越大，引入了UI组件库，又来了几个新同事，大家写的CSS文件越来越多。突然有一天，产品经理让你改一个按钮的颜色，你就写下 `.my-button { background-color: blue; }`，刷新一看，没反应！

打开F12，发现你的样式给覆盖了：

```css
#app .main-content .card-list .card:nth-child(3) .button { background-color: red; }
```

怎么办？你的第一反应通常是把自己的选择器也写得更长、更具体，用更高的“权重”把它怼回去。这就是“权重”的开始。

这时候终极方案——`!important`——往往就会登场。

`!important` 可以瞬间解决眼前的冲突，但它带来的副作用是长期的。今天你用一个，明天同事为了覆盖你的，就得用两个。最终，项目里`!important`满天飞，CSS变得像一坨屎，彻底失控。

那么解决这个问题，有希望吗？

有。今天，我们就来聊聊CSS官方给我们的分层协议—— `@layer`。

## “层叠”的规则 ##

在介绍 `@layer` 之前，我们得花一分钟，快速回顾一下CSS“层叠”（Cascade）这个词的本来意思。当多个样式规则都想作用于同一个元素时，它会根据一套严格的标准来决定谁在最上面，谁在最底层。

这个标准，简单说就三条，优先级从上到下：

- 来源和重要性：浏览器默认样式 < 我们写的样式 < 我们写的带!important的样式。
- 权重（Specificity） ：这是我们最熟悉的方式。ID选择器(如`#id`) > 类选择器/属性选择器(如`.class`, `[type="text"]`) > 标签选择器(如div)。
- 代码顺序：如果上面两条都一样，那简单粗暴，谁写在后面，谁会覆盖前面的。

过去，我们能掌控的，基本就只有第2条和第3条。所以大家只能在“提权重”和“改顺序”这两条路上卷。

## 新的规则：`@layer` ##

好了，`@layer `是什么？

你可以把它理解成，*CSS官方提供的一种给样式“分层”的工具，就像Photoshop或Figma里的图层一样*。

它引入了一个*全新的、优先级甚至高于“权重” 的判断标准*。

`@layer` 的核心规则就一句话：层叠顺序（Cascade Layers）的优先级，高于单个选择器的权重。你定义图层的顺序，决定了最终谁胜出。
这听起来有点抽象，我们直接上代码，一看就懂。

假设我们先在CSS文件的顶部，声明定义好我们的图层顺序：

```CSS
@layer reset, base, components, utilities;
```

这行代码的意思是：`reset` 层的样式最先被考虑（最底层），`utilities` 层的样式最后被考虑（最顶层）。

现在，我们写两条规则，一条权重很高，但放在了底层的 `base` 里；另一条权重很低，但放在了顶层的 `utilities` 里：

```CSS
/* 把它放进 base 图层 */
@layer base {
  /* 一个权重很高的选择器 (1个ID + 1个标签) */
  #main p {
    color: blue;
  }
}

/* 把它放进 utilities 图层 */
@layer utilities {
  /* 一个权重很低的选择器 (1个类) */
  .text-red {
    color: red;
  }
}
```

然后我们这么用：

```HTML
<div id="main">
  <p class="text-red">这段文字会是什么颜色？</p>
</div>
```

按照老的“权重”规则，`#main p` 的权重（101）远大于 `.text-red `的权重（10），所以文字应该是蓝色的。

但用了`@layer`之后，结果是：文字会是红色的！

为什么？因为`utilities`这个图层，在我们最开始定义时，就排在了`base`图层的后面。所以，无论`base`层里的选择器权重有多高，它都打不过`utilities`层里的规则。

这就是`@layer`最有意思的地方：它让我们从关注单个选择器，上升到了样式架构层面。

## 在真实项目中，我们该怎么用`@layer`？ ##

理解了原理，我们来看看在实际项目中如何搭建这个分层架构。这是我现在常用的一个分层结构：

```CSS
/* 1. 定义所有图层的顺序 */
@layer reset, base, library, components, utilities, overrides;

/* 2. 把不同类型的样式，放进对应的图层 */

/* reset.css 或 normalize.css */
@layer reset {
  /* ...重置浏览器的默认样式... */
  * { box-sizing: border-box; }
}

/* 基础元素样式 */
@layer base {
  body { font-family: sans-serif; }
  a { color: #333; }
}

/* 引入第三方UI库，比如Ant Design Vue */
@import url('ant-design-vue/dist/reset.css') layer(library);
@layer library {
  /* 你可以写一些覆盖UI库的全局样式 */
}

/* 我们自己的业务组件 */
@layer components {
  .card { border: 1px solid #eee; }
  .button { padding: 8px 16px; }
}

/* 工具类，比如Tailwind里的 */
@layer utilities {
  .text-center { text-align: center; }
  .p-4 { padding: 1rem; }
}

/* 最后的“救命稻草”层，用来覆盖一切 */
@layer overrides {
  .some-very-specific-case {
    /* ... */
  }
}
```

这个结构的好处是：

- 第三方库的样式再也不会“一手遮天”了。通过`@import ... layer(library)`，我们能把整个UI库的样式都关进一个可控的图层里。

- 工具类的优先级得到了保证。像`.text-center`这种工具类，我们总是希望它能覆盖掉组件的默认样式，现在把它放在`utilities`层，就能轻松实现。

- 我们几乎不再需要`!important`了。以前需要用`!important`的场景，现在大部分都可以通过把覆盖样式写在`utilities`或`overrides`层来解决，代码变得干净、可预测。


`@layer` 不是一个小技巧，它是CSS发展史上的一个里程碑。它为我们提供了一个前所未有的处理方式，来管理CSS的复杂性。

它让我们写CSS的思路，从“我该怎么提高这个选择器的权重去覆盖它？”，转变成了“我应该把这个样式规则放在哪个图层才最合理？”。

浏览器兼容性方面，截至2026年7月，所有主流浏览器都已支持（简单粗暴统计🙂）。所以，别犹豫了，在你的下一个项目中，尝试用`@layer`来构建你的CSS架构吧。
