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 小时前
CSS结构性伪类、UI伪类与动态伪类全解析:从文档结构到交互状态的精准选择
css·ui·交互
码农黛兮_465 小时前
CSS3 基础知识、原理及与CSS的区别
前端·css·css3
(((φ(◎ロ◎;)φ)))牵丝戏安6 小时前
根据输入的数据渲染柱形图
前端·css·css3·js
逍遥德7 小时前
CSS可以继承的样式汇总
前端·css·ui
读心悦7 小时前
CSS3 选择器完全指南:从基础到高级的元素定位技术
前端·css·css3
_龙衣8 小时前
将 swagger 接口导入 apifox 查看及调试
前端·javascript·css·vue.js·css3
为美好的生活献上中指12 小时前
java每日精进 5.11【WebSocket】
java·javascript·css·网络·sql·websocket·网络协议
asqq813 小时前
CSS 中的 ::before 和 ::after 伪元素
前端·css
拖孩13 小时前
【Nova UI】十五、打造组件库之滚动条组件(上):滚动条组件的起步与进阶
前端·javascript·css·vue.js·ui组件库
荔枝吖17 小时前
项目中会出现的css样式
前端·css·html