:has(): the family selector(译文)

113 阅读2分钟

原文出处:developer.chrome.com/blog/has-m1…

从一开始(用CSS术语来说),我们就在各种场景上使用级联(cascade)。我们的风格构成了一个“层叠风格表”。我们的选择器也是级联的。他们可以横着走。在大多数情况下,它们是向下的。但永远不要向上。多年来,我们一直幻想着一个“家长选择器”(parent selector)。现在它终于来了!他就是has伪选择器。

浏览器支持

在我们进一步讨论之前,值得一提的是对浏览器的支持。它还没有完全实现。但是,它越来越近了。目前还没有Firefox支持,它已经在路线图上了。但它已经在Safari中发布,并将在Chromium 105中发布。本文中的所有演示都会告诉您所使用的浏览器是否不支持它们。

如何使用has

那么它看起来是什么样子呢?考虑下面的HTML,其中包含两个类为everyone的同级元素。您将如何选择具有类a-good-time的子代的?

<div class="everybody">
  <div>
    <div class="a-good-time"></div>
  </div>
</div>

<div class="everybody"></div>

有了has选择器,我们可以在css中这样实现:

.everybody:has(.a-good-time) {
  animation: party 21600s forwards;
}

在这个案例中, class为everybody的Element是目标. 条件是后代中存在class为a-good-time的元素.就像下面这样。

<target>:has(<condition>) { <styles> }

然后,has()还存在很多引申的用法,甚至有些可能还没有被发现。

选择 figure elements 拥有一个直系的(direct) figcaption.

figure:has(> figcaption) { ... }

选择所有不存在 SVG 直系后代的anchor

a:not(:has(> svg)) { ... }

选择所有的存在一个直系 input 兄妹(sibling)的label. nice!

label:has(+ input) { … }

选择所有的后代的img不存在alt属性的article

article:has(img:not([alt])) { … }

选择Dom处于某个状态下的documentElement

:root:has(.menu-toggle[aria-pressed=”true”]) { … }

选择具有奇数个子项的布局容器(译者:这种感觉真duck不必了,可读性不谈。。)

.container:has(> .container__item:last-of-type:nth-of-type(odd)) { ... }

选择所有grid中不被hover的元素

.grid:has(.grid__item:hover) .grid__item:not(:hover) { ... }

选择包含自定义标签 <todo-list>的容器

main:has(todo-list) { ... }

选择所有存在单独 a子节点并且有一个 hr元素作为直接的兄妹的p标签

p:has(+ hr) a:only-child { … }

选择一个满足多个条件的article(同时包含直接的h1和h2的acticle)

article:has(>h1):has(>h2) { … }

对于:has(),你能想到哪些有趣的用例?有趣的是,它鼓励你打破你的思维模式。这会让你想“我能用不同的方式来处理这些风格吗?”。