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 中提供了强大的选择器功能,可以帮助开发者更精确地控制样式。

相关推荐
心灵的制造商1 小时前
【CSS文字渐变动画】
前端·css
BUG_Jia2 小时前
解决 uniapp 开发中权限申请同步告知目的问题| 华为应用商店上架审核问题解决
前端·javascript·css·vue.js·uni-app·css3
知识分享小能手3 小时前
CSS3学习教程,从入门到精通,CSS3 浮动与清除浮动语法知识点及案例代码(14)
前端·css·后端·学习·html·css3·html5
IT、木易13 小时前
CSS 中@media查询的工作原理,如何利用它实现不同设备的样式适配
前端·css
冰夏之夜影13 小时前
【css酷炫效果】纯CSS实现全屏万花筒效果
前端·css
拉不动的猪14 小时前
移动端适配的插件及其实现的原理
前端·javascript·css
Wiktok15 小时前
CSS实现当鼠标悬停在一个元素上时,另一个元素的样式发生变化的效果
前端·css
惜茶16 小时前
用@keyframes-animation来实现动画效果
前端·css·html
繁华是瑾16 小时前
好看的css星星效果边框
前端·javascript·css
吃杠碰小鸡1 天前
css-grid布局
前端·css