层叠层
生成规则的层选择、原生规则的归属、重要性和规则顺序。
本页内容
除非类明确选择其他受支持的层,Master CSS 都会将生成的样式规则放入 utilities。受管理的主题声明使用 theme。原生 CSS 则保留编写时所属的层,包括通过 @apply 展开混入的原生规则。
本页定义层的归属与生成规则的排序。覆盖组件或通过 DevTools 诊断的方法,见指南中的层叠层。
建立顺序
基础样式表通过 @master/css/base.css 提供,也包含在完整的 @master/css 导入中;它会声明:
@layer theme, base, defaults, components, utilities;请在其他规则建立这些层之前加载它。CSS 按首次出现的顺序确定层次,后来的顺序声明无法重新排列已建立的层。生成的层块本身不会插入这段声明。
普通声明与重要声明
这些层的普通声明互相竞争时,utilities 的优先级最高,theme 最低。不属于任何层的普通作者规则优先于所有这些层。!important 会反转层之间的顺序,并让层内的重要规则优先于无层的重要规则。这里比较的是作者样式表内部的顺序,并非涵盖来源、行内样式、动画和过渡的完整层叠。见 CSS 层排序。
重要性会反转层优先级
比较作者样式表中重要性相同的声明。无层的普通规则优先于具名层;具名层的重要规则优先于无层的重要规则。
文字说明
- 基础样式表依次声明 theme、base、defaults、components 和 utilities。
- 作者样式表的普通声明从 theme 到 utilities 优先级逐步提高,无层声明则高于所有具名层。
- 作者样式表的重要声明则朝相反方向提高优先级:theme 是这些层中最强的,无层的重要声明最弱。
- 层优先级先于选择器优先级比较。图中分别比较重要性相同的两组声明,并非将普通声明与重要声明或其他层叠来源相互比较。
层优先级先于选择器优先级判断,因此优先级更高的组件选择器,无法仅凭选择器优先级胜过普通工具类声明。同一层内的声明仍受其他层叠条件影响,见选择器优先级。
层的归属
| 层 | 生成内容 | 原生 CSS 惯例 |
|---|---|---|
theme | 保留在 :root, :host 下的受管理令牌声明 | 令牌默认值 |
base | 带有 @layer(base) 的类 | 规范化与文档基础样式 |
defaults | 带有 @layer(defaults) 的类 | 广泛的项目或内容默认样式 |
components | 带有 @layer(components) 的类 | 可复用的产品类 |
utilities | 普通工具类、组合样式、原生声明类以及显式 @layer(utilities) | 局部工具类规则 |
原生 CSS 列说明的是预期职责,并不限制 CSS 在某一层中可使用哪些属性。defaults 是项目层,不是浏览器的用户代理样式表。令牌依赖项的交付方式见变量与模式。
选择生成规则的层
类后缀只接受以下四个层名称:
@layer(base)@layer(defaults)@layer(components)@layer(utilities)该后缀选择整个生成类所属的层,不会创建子层,也不会移动该类依赖的主题变量。请将它与其他后缀一起放在结尾 ! 之前。
| 形式 | 结果 |
|---|---|
block@layer(defaults) | display 规则放入 defaults |
block@layer(base)@layer(base) | 一个 base 层规则;允许重复相同选择 |
block@layer(base)@layer(utilities) | CLASS_SYNTAX_ERROR:一个类不能选择不同的层 |
block@layer(theme) | UNKNOWN_CONDITION:theme 不是生成样式规则可选的层 |
block@layer(custom) | UNKNOWN_CONDITION:任意原生层名称不能作为类后缀目标 |
项目自有的层和子层请使用原生 @layer 语法。它们的顺序遵循原生 CSS;类后缀不会注册新的层名称。
选择样式层不会移动其令牌
两条层带显示输出的归属,并非以位置呈现完整的层叠比较。
文字说明
- p-md@layer(defaults) 将生成的 padding 声明输出到 defaults 层。
- 其 --spacing-md 依赖项仍输出在 theme 层的 :root,:host 下。@layer(defaults) 选择的是类规则的层,不是依赖项的层。
Base 与 defaults
base 层的后代规则可以建立结构基础:
<body class="(list-style:none)_ul@layer(base)">…</body>生成的 CSS
@layer base { .\(list-style\:none\)_ul\@layer\(base\) ul { list-style: none }}defaults 层的后代规则可以建立代码排版,并让局部组件与工具类的选择保持更高优先级:
<body class="font-mono_:is(code,pre)@layer(defaults)">…</body>生成的 CSS
@layer theme { :root, :host { --font-family-mono: var(--font-mono, ui-monospace), SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace }}@layer defaults { .font-mono_\:is\(code\,pre\)\@layer\(defaults\) :is(code, pre) { font-family: var(--font-family-mono) }}font-mono 类保留在 defaults 中,它需要的字体令牌仍在 theme。选择器后缀决定哪些后代元素获得声明,与层的选择相互独立。
默认样式的优先级低于局部选择
这里的两个规则都指向第一个段落。段落自身的原生声明类放在 utilities,因此会覆盖文章在 defaults 层中的字号:
<article class="(font-size:1rem)_p@layer(defaults)"> <p class="(font-size:1.5rem)">24</p> <p>16</p></article>生成的 CSS
@layer defaults { .\(font-size\:1rem\)_p\@layer\(defaults\) p { font-size: 1rem }}@layer utilities { .\(font-size\:1\.5rem\) { font-size: 1.5rem }}原生规则与受管理的工具类
位于 @layer components 内的原生类仍是原生 CSS。它默认会被交付,并遵循该层内的原生源顺序,不会获得 Master 的选择器或条件后缀。@prune native 控制未使用的原生选择器是否可以移除。
此例中的 .btn 声明 inline-flex,flex 则生成普通工具类声明。建立基础顺序后,按钮使用 display: flex:
@layer components { .btn { display: inline-flex; }}<button type="button" class="btn flex">Save</button>生成的 CSS
@layer components { .btn { display: inline-flex; }}@layer utilities { .flex { display: flex }}按需生成的 @utility 则会注册受管理的类。它的普通输出属于 utilities,但可以通过后缀选择其他受支持的层:
@utility flow { display: grid; gap: var(--spacing-md);}<div class="flow@layer(defaults)">Example</div>生成的 CSS
@layer theme { :root, :host { --spacing-md: 1rem }}@layer defaults { .flow\@layer\(defaults\) { display: grid; gap: var(--spacing-md) }}工具类定义与原生规则的保留方式,见工具类与混入。
混入展开会保留所在的层
原生规则内的 @apply 会在出现的位置展开声明,不会将该规则移到 utilities:
@mixin --inset { padding: 1.5rem;}@layer components { .card { @apply --inset; }}<div class="card p(8)">Example</div>生成的 CSS
@layer components { .card { padding: 1.5rem }}@layer utilities { .p\(8\) { padding: calc(8 * 1px) }}建立基础顺序后,工具类的 8px 内边距会胜过组件的 1.5rem。如果未将其放入层中,原生 .card 规则就不属于任何层,其普通内边距声明会优先于普通工具类。
层块必须放在混入主体和 @apply 内容之外,这些位置不接受层块。层决定整个生成规则的归属,不是用来包裹部分声明。
同一层内的优先级
HTML 中的类顺序不会决定谁优先。Master CSS 为生成规则提供稳定顺序,再由浏览器对匹配声明应用层叠。在可比较的层、选择器和条件上下文中,生成规则按以下顺序排列:
包含多个声明,或包含内部选择器与条件的组合样式。
单声明工具类,包括固定、令牌驱动和直接值工具类。
原生声明类。
单声明工具类按属性族和覆盖范围排序:单边或单轴规则排在整个族之后。属性和作用域相同时,具名令牌值排在直接值之前。重要性、选择器优先级和条件仍参与判断;直接值并不总能胜过其他作用域或层中的令牌。
以下示例使用预设、基础层声明以及 16px 的根元素字号。竞争的声明指向同一个元素,而且条件均匹配。
| 竞争的类或规则 | 结果 | 原因 |
|---|---|---|
p-md p(8),顺序不限 | padding: 8px | 相同属性和作用域中,直接值排在令牌之后 |
p(8) (padding:2rem),顺序不限 | padding: 2rem | 原生声明排在单声明工具类之后 |
m-md mt(0),顺序不限 | 上外边距 0;其他外边距 1rem | 单边排在整个外边距族之后 |
b(2) bt(0) b-solid b-red-60 | 上边宽 0;其他边宽 2px;红色实线边框 | 宽度、样式和颜色是独立的族 |
p-md! p(8) | padding: 1rem | 重要性先于值来源排序 |
p-md! p(8)! | padding: 8px | 重要性相同;直接值排在令牌之后 |
p(8)@layer(base) p(12) | padding: 12px | 普通工具类优先于 base |
p(8)@layer(base)! p(12)! | padding: 8px | 重要声明反转层优先级 |
无层的 .outside { padding: 32px; } 与 p(8) | padding: 32px | 无层的普通声明优先于层内声明 |
components 层的 padding: 24px !important 与 p(8)! | padding: 24px | 重要声明之间,以较早的层优先 |
层内的原生规则保留编写时的顺序,上述生成工具类的排序不会重新排列它们。声明重叠时请检查输出的 CSS,并使用代码 lint,在编写时找出冲突的类。



