CSS Handbook · 自定义属性与现代函数

第十章 / 10.3 @layer 层叠层与 @scope

第十章 · 10.3 节

@layer 层叠层与 @scope


回到 1.2 节留下的伏笔:当项目规模变大、样式来源变多(重置样式、组件库、页面覆写、第三方样式),仅凭选择器优先级早晚已经很难管理覆盖关系。@layer 与 @scope 是 CSS 为解决这一"规模化"问题给出的现代方案。

大型项目中的优先级困局

设想这样的场景:组件库定义了 .button 的样式,页面级代码想要覆盖它的颜色,却因为组件库内部用了更具体的选择器(比如 .card .button),导致页面样式怎么写都覆盖不掉——只能被迫升高选择器权重甚至滥用 !important,样式表因此逐渐失控。

@layer 基本用法

@layer 把样式划分进"层叠层",层与层之间有明确的优先级顺序,与每层内部的选择器权重完全无关——后声明的层整体覆盖先声明的层,哪怕后者选择器权重再低。

/* 第一步:声明层的顺序(越靠后优先级越高) */
@layer reset, base, components, utilities;

/* 第二步:把样式放进对应的层 */
@layer reset {
  * { margin: 0; }
}
@layer components {
  .card .button { color: gray; } /* 权重更高,但层更低 */
}
@layer utilities {
  .button { color: teal; } /* 权重更低,但层更高 —— 生效 */
}
关键规则任何显式分层的规则,优先级都高于未分层的普通规则——但都低于内联样式与 !important(且 !important 在层间的覆盖顺序是反过来的:先声明的层里的 !important 反而更高)。

层的声明顺序即优先级顺序

第一次遇到某个层名时就确定了它在层叠顺序中的位置,之后可以在文件的任意位置多次追加同名 @layer 块,内容会合并,但顺序不会改变——这让"先规划层级结构,再分批填充内容"成为可能,非常适合拆分到多个 CSS 文件维护。

/* reset.css */
@layer reset { ... }

/* components.css,晚于 reset.css 加载也没关系 */
@layer components { ... }

@scope:限定样式作用范围

@scope 解决的是另一个问题:让一组样式只在指定的 DOM 子树内生效,不会"泄漏"影响到无关区域,天然适合给可能被嵌套复用的组件加边界:

@scope (.card) to (.card-nested) {
  p { color: #5c5872; }
}
/* 只作用于 .card 内部的 p,且遇到 .card-nested 就停止向下作用 —— 避免影响卡片内嵌套的另一个卡片 */

全书回顾

从最基础的标签选择器,到能够表达复杂组件关系的伪类组合;从静态的盒模型,到能响应视口与容器变化的 Flexbox、Grid 与媒体/容器查询;再到颜色、渐变、动效与变量系统——这七章内容构成了现代 CSS 的核心骨架。真正的熟练,来自把它们组合起来解决具体问题:下一步,不妨挑一个你正在做(或想做)的页面,试着只用本书讲过的知识,从零把它搭建出来。

Chapter 10 · Section 10.3

@layer Cascade Layers and @scope


Back to the thread left dangling in Section 1.2: as projects grow and style sources multiply (reset styles, component libraries, page overrides, third-party styles), selector specificity alone soon stops being manageable. @layer and @scope are the modern CSS answer to this "scaling" problem.

The Specificity Predicament in Large Projects

Picture this: a component library defines the styles for .button, and page-level code wants to override its color — but because the library internally uses a more specific selector (such as .card .button), the page styles can never win. The only way out is to keep inflating the specificity or abuse !important, and the style sheet gradually spirals out of control.

@layer Basics

@layer divides styles into "cascade layers" with a well-defined priority order between layers, completely independent of the selector specificity inside each layer — a later-declared layer overrides earlier layers as a whole, no matter how low its selectors' specificity is.

/* Step 1: declare the layer order (later layers win) */
@layer reset, base, components, utilities;

/* Step 2: put styles into their corresponding layers */
@layer reset {
  * { margin: 0; }
}
@layer components {
  .card .button { color: gray; } /* higher specificity, but a lower layer */
}
@layer utilities {
  .button { color: teal; } /* lower specificity, but a higher layer — it wins */
}
Key ruleAny explicitly layered rule beats unlayered normal rules — but all of them lose to inline styles and !important (and !important reverses the order between layers: an !important in an earlier-declared layer actually wins).

Layer Declaration Order Is the Priority Order

A layer's position in the cascade order is fixed the first time its name appears; afterwards you can append more @layer blocks with the same name anywhere in the file, and their contents merge without changing the order — which makes it possible to "plan the layer structure first, then fill in content in batches", ideal for splitting maintenance across multiple CSS files.

/* reset.css */
@layer reset { ... }

/* components.css — loading after reset.css is fine */
@layer components { ... }

@scope: Restricting Where Styles Apply

@scope solves a different problem: it keeps a set of styles effective only within a specified DOM subtree, so they never "leak" into unrelated areas — a natural way to fence off components that may be nested and reused:

@scope (.card) to (.card-nested) {
  p { color: #5c5872; }
}
/* applies only to p inside .card, and stops descending at .card-nested — so it never affects another card nested inside */

A Look Back at the Whole Book

From the simplest tag selector to pseudo-class combinations that express complex component relationships; from the static box model to Flexbox, Grid and media/container queries that respond to viewport and container changes; and on to color, gradients, motion and the variable system — these seven chapters form the core skeleton of modern CSS. Real fluency comes from combining them to solve concrete problems: as a next step, pick a page you are building (or want to build) and try to construct it from scratch using only what this book has covered.