CSS 系列:新特性 `:scope` 和 `@scope` ✨

🎯 一句话总结

:scope@scope 二者都是指向被引用的元素本身。

  • :scope 是伪类用在 CSS / JS 选择器中。
  • @scope 是新的 CSS 语法,类似社区的 CSS Module,用在 style 标签内。

下面从实际使用场景来说明。

:scope 用在 CSS 中 💅

假设有 HTML 结构如下,想让其本身是蓝色,子元素 p 是红色。

html 复制代码
<section>
  <p>...</p> // <- 目标
  
  <div>
    <p>...</p>
  </div>
</section>

可以用这样一种 CSS 新范式来写:

html 复制代码
<section>
  <style>
    @scope {...}
  </style>
  ...
</section>

@scope 将范围限制在元素内部,:scope 指向元素本身,二者组合堪称完美!

html 复制代码
<section>
  <style>
    @scope {
      :scope { color: blue; } /* 选择 section 本身 */
      :scope > p { color: red; } /* 选择子元素而非嵌套元素 */
    }
  </style>

  <p>第一个子元素 color 为 red</p>
  
  <div>
    <p>第二个子元素继承 color 为 blue</p>
  </div>
</section>

@scope 仅将样式限制在它所在的 DOM 节点的子元素上,而 :scope 选择器是一种为节点本身设置样式的方法。

这种写法下,即使我们用了很通用的 tag 选择器,仅却仅影响当前范围内的 p,相当于 CSS Module。 在 section 之外的元素不受任何影响,隔绝仿若孤岛, 即非 red 也非 blue。

那和嵌套有何区别?

不用 @scope:scope 原来我们需要这么写.

首先得给 section 增加 .parent 否则无法在 CSS 中选中。

html 复制代码
<section class="parent">
  ...

然后嵌套:

html 复制代码
<style>
.parent {
  color: red
  & > p:first-child {
    color: red
  }
}
</style>

嵌套写法的缺点:

  • 需要增加 class ,而这个 class 如果仅为了 css,就显得有些多余,有时它只是一个临时起的名字,之所以存在只是因为没有其他方法。而"命名是计算机科学中最难的两件事之一"。
  • 维护性差 :仔细观察 @scope 发现样式和 HTML 是紧密相连的,好处是不会出现臃肿的无用的 CSS,甚至以后都不敢删除(这也是 Vue 的单文件优于 React 的原因之一)。
  • 会增加CSS权重 :而 @scope 并不会改变其权重,比如 @scope { p } p 仍然是 0, 0, 1

:scope 用在 JS 中

比如,我们已经有一个元素(这是我们的前提),想获取其直接子元素。

html 复制代码
<div id="parent">
  <p>...</p> // <- 目标
  <p>...</p>
</div>

假设我们已经获取到了 parent 元素

js 复制代码
parent.querySelect('...') // 这里如何写能获取到第一个 p

注意下面写法是不对的,会报错非法的 CSS selector

js 复制代码
parent.querySelect('> p') // ❌

Uncaught DOMException: Element.querySelector: '> div' is not a valid selector

答案:可以用 :scope,因为它可以指代本身。

js 复制代码
parent.querySelect(':scope > p')

🧠 总结

1 :scope 匹配的元素取决于它的使用上下文:

2 @scope CSS 规则使你能够选择特定 DOM 子树中的元素,精确地定位元素,而无需编写难以覆盖的过于具体的选择器 ,也无需将选择器与 DOM 结构过于紧密地耦合

📚 参考

🔍 扩展

除了 :scope 还有哪些特殊的伪类? 以下是一些类似的伪类选择器:

  1. :root

    • 表示文档的根元素,通常是 <html> 元素。
    • 示例::root { background-color: white; }
  2. :host

    • 在 Shadow DOM 中使用,表示 Shadow DOM 的宿主元素。
    • 示例::host { display: block; }
  3. :host-context()

    • 在 Shadow DOM 中使用,表示宿主元素的上下文环境。
    • 示例::host-context(.dark-theme) { background-color: black; }
  4. :is()

    • 用于组合多个选择器,匹配其中任意一个。权重取其中最大的
    • 示例::is(#header.header, #footer) h1 { color: green; } 权重为 1-1-1
      • :is(#header.header, #footer) 权重为 #header.header 的权重即 1-1-0
      • h10-0-1,整体权重为 1-1-1
  5. :where()

    • :is() 类似,但被其包裹的选择器的特异性或权重为 0,或者说不会增加权重 ,这也就是为何 antd 选择使用 where 而非 is 的原因。其次 :where 还有一个好处内部存在无效的选择器并不会导致整体失效,is 同样如此。
    • 示例::where(#header, #footer) h1 { color: green; } 即使存在 id 选择器,其整体权重仍然为h1 的权重 0-0-1 。即便 header h1 { color: violet; } 甚至 h1 { color: violet; } 也能轻松将其覆盖。

无效的选择器并不会导致整体失效,`:is` 同样如此

  1. :not()

    • 用于排除特定的选择器。
    • 示例::not(.class1) { color: green; }
  2. :has()

    • 用于选择包含特定子元素的元素。
    • 示例::has(> .child) { background-color: yellow; }
  3. :empty

    • 匹配没有子元素的元素(包括没有文本节点)。
    • 示例:p:empty { display: none } 隐藏所有空节点避免影响布局

这些内置关键词和伪类选择器在 CSS 中提供了强大的选择器功能,可以帮助开发者更精确地控制样式。

相关推荐
加个鸡腿儿2 小时前
经验分享2:SSR 项目中响应式组件的闪动陷阱与修复实践
前端·css·架构
华仔啊3 小时前
写 CSS 用 px?这 3 个单位能让页面自动适配屏幕
前端·css
菩提小狗4 小时前
Sqli-Labs Less-3 靶场完整解题流程解析-豆包生成
前端·css·less
web小白成长日记8 小时前
CSS 作用域隔离实战:React、Vue 与 Styled Components 的三种范式
前端·css·vue.js·react.js
@@小旭21 小时前
实现头部Sticky 粘性布局,并且点击菜单滑动到相应位置
前端·javascript·css
Irene19911 天前
CSS 定位属性(relative、absolute、fixed、sticky)与实用技巧总结
css
我的写法有点潮1 天前
推荐几个国外比较流行的UI库(上)
前端·javascript·css
m0_502724951 天前
vue动态设置背景图片后显示异常
前端·css
@Autowire1 天前
Layout-position
前端·css
神秘的猪头1 天前
🎨 CSS 这种“烂大街”的技术,怎么在 React 和 Vue 里玩出花来?—— 模块化 CSS 深度避坑指南
css·vue.js·react.js