前置知识: CSS

层叠层

1 min高级

@layer

前置依赖:先读 009 优先级计算,理解层叠顺序。

1. @layer 概述

CSS 层叠层(Cascade Layers)允许开发者将 CSS 规则分组到不同的层中,控制层叠优先级。

@layer reset, base, components, utilities;

@layer reset {
  * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
}

@layer base {
  body {
    font-family: sans-serif;
    line-height: 1.6;
  }
}

@layer components {
  .card {
    border-radius: 8px;
    padding: 1rem;
  }
}

@layer utilities {
  .hidden {
    display: none;
  }
}

2. 层优先级

后声明的层优先级更高:reset < base < components < utilities

未分层的规则优先级最高(高于所有层)。

3. 嵌套层

@layer framework {
  @layer base {
    .btn {
      padding: 8px;
    }
  }
  @layer theme {
    .btn {
      color: blue;
    }
  }
}

/* 引用嵌套层 */
@layer framework.theme {
  .btn {
    color: red;
  }
}

4. @import 与 @layer

@import url('reset.css') layer(reset);
@import url('base.css') layer(base);

5. 最佳实践

  • 使用 @layer 声明层顺序
  • 第三方样式放在低优先级层
  • 自定义样式放在高优先级层
  • 工具类放在最高优先级层

@layer 定义

基本写法:定义命名层 @layer <层名>;

/* 声明层叠层 */
@layer base;
@layer components;
@layer utilities;

基本写法:定义并写入样式 @layer <层名> { <样式> }

/* 定义层并写入样式 */
@layer base {
  body {
    font-size: 16px;
  }
}

单行写法:多层级声明 @layer <层1>, <层2>, <层3>;

/* 单行声明多个层叠层顺序 */
@layer base, components, utilities;

换行写法:多层级声明 @layer <层1>, <层2>, <层3>;

/* 换行声明多个层叠层顺序 */
@layer
  base,
  components,
  utilities;

基本写法:匿名层 @layer { <样式> }

/* 创建匿名层叠层 */
@layer {
  .box {
    padding: 10px;
  }
}

层优先级

基本写法:层顺序决定优先级 @layer <低优先级>, <中优先级>, <高优先级>;

/* 后声明的层优先级更高 */
@layer base, components, utilities;
@layer base {
  p { color: black; }
}
@layer utilities {
  p { color: red; }
}

基本写法:未分层样式优先 <选择器> { <样式> }

/* 未分层样式优先级高于所有层 */
p {
  color: blue;
}
@layer base {
  p { color: black; }
}

基本写法:层内 !important 反转 <选择器> { <属性>: <值> !important; }

/* !important 在层间反转优先级 */
@layer base {
  p { color: black !important; }
}
@layer utilities {
  p { color: red; }
}

嵌套层

基本写法:嵌套层定义 @layer <父层>.<子层> { <样式> }

/* 定义嵌套层叠层 */
@layer components.buttons {
  .btn {
    padding: 8px 16px;
  }
}

基本写法:嵌套层顺序 @layer <父层>.<子层1>, <父层>.<子层2>;

/* 声明嵌套层顺序 */
@layer components.buttons, components.forms;

基本写法:嵌套层内定义 @layer <父层> { @layer <子层> { <样式> } }

/* 在父层内定义子层 */
@layer components {
  @layer buttons {
    .btn { padding: 8px; }
  }
  @layer forms {
    .input { padding: 4px; }
  }
}

@import 分层导入

基本写法:@import 导入到层 @import url("<文件>") layer(<层名>);

/* 导入样式到指定层 */
@import url("reset.css") layer(base);

基本写法:@import 带媒体查询导入层 @import url("<文件>") layer(<层名>) <媒体查询>;

/* 导入样式到层并应用媒体查询 */
@import url("mobile.css") layer(components) (max-width: 768px);

层与特异性

基本写法:层优先于特异性 @layer <层名> { <高特异性选择器> { <样式> } }

/* 层优先级高于选择器特异性 */
@layer base {
  #header {
    color: black;
  }
}
.text-red {
  color: red;
}

基本写法:同层内特异性生效 @layer <层名> { <低特异性>, <高特异性> { <样式> } }

/* 同一层内特异性正常生效 */
@layer base {
  p { color: black; }
  .highlight { color: red; }
}

实际应用模式

基本写法:重置层 @layer base { <重置样式> }

/* 将重置样式放入 base 层 */
@layer base {
  * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
}

基本写法:组件层 @layer components { <组件样式> }

/* 将组件样式放入 components 层 */
@layer components {
  .card {
    padding: 16px;
    border: 1px solid #ccc;
  }
}

基本写法:工具层 @layer utilities { <工具样式> }

/* 将工具类样式放入 utilities 层 */
@layer utilities {
  .text-center { text-align: center; }
  .mt-4 { margin-top: 1rem; }
}

基本写法:主题层 @layer theme { <主题样式> }

/* 将主题样式放入 theme 层 */
@layer theme {
  :root {
    --primary: #007bff;
  }
}

层叠层与级联

基本写法:层顺序覆盖 @layer <低层>, <高层>;

/* 后声明的层覆盖先声明的层 */
@layer base, theme, components;
@layer base {
  body { background: white; }
}
@layer theme {
  body { background: #f5f5f5; }
}

基本写法:层内顺序 @layer <层名> { <样式1> <样式2> }

/* 同层内后定义的覆盖先定义的 */
@layer components {
  .btn { color: black; }
  .btn { color: red; }
}

层与媒体查询

基本写法:媒体查询中重新排序 @media <条件> { @layer <新顺序>; }

/* 响应式调整层顺序 */
@media (max-width: 768px) {
  @layer base, utilities, components;
}

基本写法:层内媒体查询 @layer <层名> { @media <条件> { <样式> } }

/* 在层内使用媒体查询 */
@layer components {
  .container {
    width: 100%;
    @media (min-width: 768px) {
      max-width: 720px;
    }
  }
}

层调试

基本写法:层顺序检查 @layer <层1>, <层2>, <层3>;

/* 通过声明顺序检查层优先级 */
@layer base, components, utilities;

基本写法:层覆盖测试 @layer <测试层> { <选择器> { <样式> } }

/* 临时添加层测试覆盖 */
@layer test {
  .box {
    border: 2px solid red;
  }
}

@layer 与 @scope 进阶

基本写法:@layer 命名层叠层 @layer <层1>, <层2>, <层3>;

/* 通过命名层叠层管理样式优先级 */
@layer reset, base, components, utilities;
@layer reset {
  * { margin: 0; padding: 0; box-sizing: border-box; }
}
@layer utilities {
  .text-center { text-align: center; }
}

基本写法:@layer 匿名层 @layer { <样式声明> }

/* 匿名层按声明顺序参与层叠 */
@layer {
  /* 该样式进入匿名层,优先级低于未分层样式 */
  p { line-height: 1.5; }
}

基本写法:@scope 与 @layer 对比 @layer <层名> { <样式> } vs @scope (<选择器>) { <样式> }

/* @layer 控制优先级,@scope 控制作用范围 */
@layer components {
  /* 通过层序控制优先级 */
  .title { color: black; }
}
@scope (.article) {
  /* 通过作用域限定应用范围 */
  .title { font-size: 1.5rem; }
}

基本写法:@scope 与 cascade origins @scope (<根>) to (<下限>) { <样式声明> }

/* @scope 不影响优先级,仅限定范围 */
@scope (.content) to (.ad) {
  /* 仅作用于 .content 内、.ad 之外 */
  a { color: #007bff; }
}
/* @scope 内样式特异性仍按选择器计算 */

动手试试

  1. 声明 @layer reset, base, components, utilities 并各写一条同权重规则,观察优先级;
  2. 把第三方库样式放进 @layer vendor,确认能被业务层覆盖;
  3. 用 @layer 替代 !important 解决一次覆盖问题;
  4. 进阶挑战:对比 @layer 与 @import layer() 的用法。

核心知识点

一句话记住 @layer:层顺序决定胜负(后声明的层优先),层内再看权重;第三方样式进层,业务样式出层。

  • @layer a, b, c 声明层顺序,后面的层优先级高;
  • 未分层样式优先级高于所有分层样式;
  • 层内仍按选择器权重与顺序计算;
  • 适合管理 reset、框架、组件、工具类;
  • 与 !important 的交互:important 反转层顺序。

注意事项与改进建议

问题点说明改进方案
层顺序搞反覆盖失败声明顺序即优先级
全部塞进层调试困难只给可覆盖的样式分层
与 !important 混用行为反转明确层优先级语义
旧浏览器不支持层不生效提供无层兜底

扩展学习

  • 优先级:css/170-PriorityCalculation;
  • 架构:css/560-CSSArchitectureMethodology;
  • 新特性:css/650-CSSNewFeatures。