学习 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 特性。不过我相信在不久的将来,主流浏览器会对其有更好的支持度。

相关推荐
啧不应该啊1 小时前
vue配置axios
前端·javascript·vue.js
Zww08911 小时前
html,css基础知识点笔记(二)
css·笔记·html
__fuys__1 小时前
【HTML样式】加载动画专题 每周更新
前端·javascript·html
给bug两拳1 小时前
HTML/CSS/JS学习笔记 Day5(CSS--C2 元素的显示模式)
css
界面开发小八哥1 小时前
DevExpress WinForms v24.1新版亮点:升级的HTML & CSS支持
css·html·界面控件·winform·devexpress·用户界面
Want5951 小时前
HTML粉色烟花秀
前端·css·html
让开,我要吃人了2 小时前
HarmonyOS鸿蒙开发实战(5.0)自定义全局弹窗实践
前端·华为·移动开发·harmonyos·鸿蒙·鸿蒙系统·鸿蒙开发
yanlele2 小时前
前端面试第 66 期 - Vue 专题第二篇 - 2024.09.22 更新前端面试问题总结(20道题)
前端·javascript·面试
一条晒干的咸魚2 小时前
响应式CSS 媒体查询——WEB开发系列39
前端·css·html·css3·响应式设计·媒体查询
凌晨五点的星2 小时前
网络安全-webshell绕过,hash碰撞,webshell绕过原理
开发语言·前端·javascript