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

CSS 社区模块化方案

概述简介

在前端快速的发展中, CSS 一直缺乏模块化的概念。由于 CSS 是根据选择器进行全局元素的匹配,它没有作用域可言。但随着项目越来越大,参与的人越来越多,命名冲突的问题日趋严重。于是 CSS 社区逐渐诞生了相应的模块化解决方案:Atomic CSS、OOCSS、BEM、SMACSS、ITCSS、CSS 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 特性。不过我相信在不久的将来,主流浏览器会对其有更好的支持度。

相关推荐
zeng不错11 分钟前
B站 173 个投稿活动看到眼瞎?我写了个扩展,主打一个精准打击
前端
Latchh13 分钟前
前端导出的JPEG红字发糊,质量要拉到100才清楚
前端·图像处理·人工智能·计算机视觉
默_笙1 小时前
🚦 请三个 AI 考官给 RAG 打分:量化评估实战(下)
前端·javascript
Joy T1 小时前
聊天系统中五大ID的演进与实战解析
java·前端·人工智能·spring·agent入门
Seraphina362 小时前
DVWA(SQL注入-low,medium,XSS反射-low)
前端·数据库·笔记·sql·网络安全·web·xss
Access开发易登软件3 小时前
Access 导入 Markdown 表格:把文档里的数据写进表
前端·html·vba·markdown·access开发
扶风ff3 小时前
求职笔试资料太散?用练题簿在线刷题,按岗位整理练习清单
前端·学习·小程序
浪浪山_大橙子3 小时前
公司里的 AI,终于不只会聊天:我用 GPT‑6 把企业工作伙伴开源了
前端·后端·面试
琹箐3 小时前
命令行调用接口
前端
可乐鸡翅yeah_4 小时前
AES‑128 加密 M3U8,IV 初始化向量新手容易踩坑
前端·网络·数据库·ffmpeg·音视频·m3u8在线