学习 CSS At Rules 作用域样式 — @scope

CSS 社区模块化方案

概述简介

在前端快速的发展中, CSS 一直缺乏模块化的概念。由于 CSS 是根据选择器进行全局元素的匹配,它没有作用域可言。但随着项目越来越大,参与的人越来越多,命名冲突的问题日趋严重。于是 CSS 社区逐渐诞生了相应的模块化解决方案:Atomic CSSOOCSSBEMSMACSSITCSSCSS Modules 以及 CSS-In-JS

模块化分类

  • CSS Namespace: 通过人工约定命名规则
  • CSS Modules: 一个 CSS 文件,一个独立的模块
  • CSS-In-JS: 在 Javascript 中写 CSS

CSS 原生作用域方案

上述中,我们讲解了来自于 CSS 社区的模块化方案,但它们都需要额外的工具或者语法,对于小型项目来说,使用起来还是比较麻烦。但现在有了 CSS 原生作用域的提案,它提供了一种新语法 @scope 来实现局部作用域,或许 CSS 样式隔离的新时代即将到来。 (确切来说,是选择器隔离)

概念说明

来自 https://drafts.csswg.org/css-cascade-6/#at-ruledef-scope

A scope is a subtree or fragment of a document, which can be used by selectors for more targeted matching. A scope is formed by determining:

  • The scoping root node, which acts as the upper bound of the scope, and optionally:
  • The scoping limit elements, which act as the lower bounds.

An element is in scope if:

  • It is an inclusive descendant of the scoping root, and
  • It is not an inclusive descendant of a scoping limit.

作用域可以是 document 的子树或片段,选择器使用它进行更有针对性的匹配。作用域的范围通过如下两点确定:

  • 作用域根节点,它作为作用域的上限
  • 作用域限制元素,它作为作用域的下限(可选)

如果同时满足以下两种情况,则元素在作用域范围中:

  • 它是作用域根节点的 包容性后代
  • 它不是作用域限制元素的 包容性后代

语法定义

作用域样式属于 CSS At Rules 中一种,在 CSS 语法中使用 @scope 进行描述,它声明了与一组样式规则关联的作用域根节点和作用域限制元素。 它具有近度优先的特性 (Proximity precedence)

css 复制代码
  /* 定义 */
  @scope [(<scope-start>)]? [to (<scope-end>)]? {
    /* <rule-list> */
  }
  
  
  /* 例 1 */
  @scope (.card) {
    :scope { /* 匹配 .card 自身样式 */ }
  }
  
  /* 例 2 */
  @scope (.card) {
    > img { /* 匹配 .card > img 样式 */ }
    & > img { /* 匹配 .card > img 样式 */ }
    :scope > img { /* 匹配 .card > img 样式 */ }
  }
  
  /* 例 3 */
  @scope (.card) to (.content) {
    img { /* 匹配 .card 到 .content 之间 img 样式, 不包含 img.content */ }  
  }
  
  /* 例 4 */
  @scope (.card) to (:scope > .content) {
    img { /* 匹配 .card img, 但是不匹配 .card > .content img */ }  
  }
  
  • <scope-start> 是一个 CSS 选择器,用于标识作用域根节点
  • <scope-end> 是一个 CSS 选择器,用于标识作用域限制元素
  • <rule-list> 表示作用域声明的样式

注意事项:

在上面 例子2:scope& 有着相同的作用,都匹配了 .card > img 的样式,但其实两者之间还是有很大的区别:

  • :scope 表示匹配的作用域根节点,而 & 则表示匹配作用域根节点的选择器 (可重复使用)。

    css 复制代码
     @scope (.card) {
      :scope :scope { 
        /* ❌ 不能工作 */ 
      }
      
       & > & { 
         /* 匹配 .card > .card 样式 */  
       }
     }
     
  • 它们还有一个区别,是在参与 CSS优先级权重计算时,表现不一样,具体会在下个小节 优先级权重 中进行说明。

优先级权重

@scope 本身不会影响 CSS 优先级权重计算,但是 :scope& 对 CSS优先级有着不同的权重

  • @scope
css 复制代码
  @scope (#card) {
    img { /* Specificity = (0,0,1) --- img 为 0,0,1 */ }
  }

  /* 就优先级权重而言,相当于 :where(#card) img */
  • :scope
css 复制代码
  @scope (#card) {
    :scope img { /* Specificity = (0,1,1) --- :scope 为 0,1,0; img 为 0,0,1 */ }
  }
  • &
css 复制代码
  @scope (#card) {
    & img { /* Specificity = (1,0,1) --- & 为 1,0,0; img 为 0,0,1 */ }
  }

  /* 就优先级权重而言,相当于 :is(#card) img */

应用场景范例

  • @scope (.card) { /* ... */ }

    css 复制代码
      @scope (.card) {
        img {
          border-color: green;
        }
      }
  • @scope (.card) to (.card__content) { /* ... */ }

    css 复制代码
      @scope (.card) to (.card__content) {
        img {
          border-color: green;
        }
      }
  • @scope { /* ... */ }

    html 复制代码
      <div class="card">
        <div class="card__header">
          <style>
            @scope {
              img {
                border-color: green;
              }
            }
          </style>
          <h1>Card Title</h1>
          <img src="..." height="32" class="hero">
        </div>
        <div class="card__content">
          <p><img src="..." height="32"></p>
        </div>
      </div>

浏览器兼容性

目前只有谷歌浏览器 (v118+) 支持了 CSS @scope 特性。不过我相信在不久的将来,主流浏览器会对其有更好的支持度。

相关推荐
Ticnix23 分钟前
ECharts初始化、销毁、resize 适配组件封装(含完整封装代码)
前端·echarts
纯爱掌门人26 分钟前
终焉轮回里,藏着 AI 与人类的答案
前端·人工智能·aigc
twl30 分钟前
OpenClaw 深度技术解析
前端
崔庆才丨静觅33 分钟前
比官方便宜一半以上!Grok API 申请及使用
前端
星光不问赶路人41 分钟前
vue3使用jsx语法详解
前端·vue.js
天蓝色的鱼鱼1 小时前
shadcn/ui,给你一个真正可控的UI组件库
前端
布列瑟农的星空1 小时前
前端都能看懂的Rust入门教程(三)——控制流语句
前端·后端·rust
Mr Xu_1 小时前
Vue 3 中计算属性的最佳实践:提升可读性、可维护性与性能
前端·javascript
jerrywus1 小时前
我写了个 Claude Code Skill,再也不用手动切图传 COS 了
前端·agent·claude
玖月晴空1 小时前
探索关于Spec 和Skills 的一些实战运用-Kiro篇
前端·aigc·代码规范