CSS 中的兄弟作用域, :has() 和 ~

119 阅读2分钟

image.png

利用 CSS :has() 选择两个元素边界之间的所有同级元素。

创建兄弟作用域

假设您有这样的标记:

<ul>
  <li>outside</li>
  <li class="from">from</li>
  <li>in-between</li>
  <li>in-between</li>
  <li>in-between</li>
  <li>in-between</li>
  <li class="to">to</li>
  <li>outside</li>
</ul>

如果你想选择 .from 和 .to 元素之间的所有元素,您可以使用万能的 :has()选择器 提供的选择器:

.from ~ :has(~ .to) {
  outline: 1px solid red;
}

它的工作原理如下:

  • .from ~ * 将选择所有以 .from 开头的元素。
  • :has(~ .to) 将选择所有后跟 .to 的元素。
  • 通过组合两者,您可以限制选择并在 .from 和 .to 兄弟之间创建一个范围。

如果要包含边界,请创建一个选择器列表:

.from,
.from ~ :has(~ .to),
.to {
	outline: 1px solid red;
}

技术演示

CodePen演示 如图:

image.png

限制

如技术演示所示, .from ~ :has(~ .to) 是贪婪的。如果你有两组相邻的边界,它们也是彼此的兄弟姐妹,选择器将选择第一个 .from 到最后一个 .to 之间的所有内容。

<ul>
  <li>outside</li>
  <li class="from">from</li>
  <li>in-between</li>
  <li>in-between</li>
  <li class="lower">to</li>
  <li class="from">from</li>
  <li>in-between</li>
  <li>in-between</li>
  <li class="lower">to</li>
  <li>outside</li>
</ul>

根据用例,这可能会或可能不会被看为限制。

浏览器支持

所有支持: has ()的浏览器都支持这些选择器。在编写本文时,这还不包括 Firefox。

👨‍🔬 在 Firefox 中打开实验性的 :has() 支持也没有用。它的实现仍处于试验阶段,因为它还不支持所有类型的选择。相对选择器解析(即 a:has(~ b) )是尚未支持的功能之一 - 跟踪错误: #1774588

您可以在不支持 :has() 的浏览器中使用以下选择器

.from ~ :not(.to):not(.to ~ *) {
    outline: 1px solid red;
}

实际应用

如构建了一个日期选择器,可以突出显示您首选的开始日期和结束日期之间的日子。

image.png

因为他们需要跨 <tr> 元素来选择元素,所以代码非常复杂并且有点难以掌握。基本上,它针对具有 :checked 输入的单元格和您当前悬停的单元格之间的所有单元格。

🤔 如果使用 list + CSS 网格来构建日历,那么样式设计就会容易得多。

参考资源:Sibling Scopes in CSS, thanks to :has() and ~