作为“父选择器”的先驱,:has()
伪类的范围远比仅仅为元素的祖先设置样式大得多。凭借其在 Safari 15.4+ 和 Chromium 105+ 中的可用性,以及在 Firefox 中的标志,现在是您熟悉:has()
其用例的好时机。
作为一个伪类,它的基本功能:has()
是设置它所附加的元素的样式——也就是所谓的“目标”元素。这类似于其他伪类,如:hover
or :active
,a:hover
旨在为<a>
处于活动状态的元素设置样式。
然而,:has()
也类似于:is()
, :where()
, 和:not()
,因为它接受括号内的相对选择器列表。这允许:has()
创建复杂的标准来测试,使其成为一个非常强大的选择器。
为了感受它是如何:has()
工作的,让我们看一个如何应用它的例子。在下面的选择器中,我们测试一个<article>
元素是否有一个<img>
子元素:
article:has(img) {}
此选择器的可能结果如下图所示。显示了三个文章元素,其中两个包含图像,并且都具有浅绿色背景和与没有图像的元素不同的填充。
只要<img>
元素存在于该<article>
元素的任何位置,上面的选择器就会应用——无论是作为直接子元素还是作为其他嵌套元素的后代。
如果我们想确保规则仅适用于元素<img>
的直接(非嵌套)子元素<article>
,我们还可以包含子组合器:
article:has(> img) {}
此更改的结果如下图所示。显示了相同的三张卡片,但这次只有图像是 的直接子代的那一张<article>
具有浅绿色背景和填充。
在这两个选择器中,我们定义的样式都应用于目标元素,即<article>
. 这就是为什么人们经常称其为:has()
“父级”选择器:如果某些元素以某种方式存在,则它们的“父级”会收到指定的样式。
注意::has()
伪类本身不会为选择器添加任何特异性权重。:is()
和一样:not()
, 的特异性:has()
等于选择器列表中特异性最高的选择器。例如,:has(#id, p, .class)
将具有赋予id
. 要复习特异性,请查看 CSS Master, 3rd Edition 中关于特异性的部分。
如果目标元素后跟特定的兄弟元素,我们还可以使用相邻兄弟组合器 ( +
) 选择目标元素。在下面的例子中,我们<h1>
只选择一个紧跟 an 的元素<h2>
:
h1:has(+ h2) {}
在下图中,<article>
显示了两个元素。在第一个中,因为<h1>
后面跟着一个<h2>
,所以<h1>
应用了浅绿色背景。
使用通用兄弟组合器 ( ~
),我们可以检查特定元素是否是目标后面任何位置的兄弟。在这里,我们正在检查某处是否有一个<p>
元素作为 的兄弟元素<ul>
:
ul:has(~ p) {}
下图显示了两个<article>
元素,每个元素都包含一个无序列表。第二篇文章的列表后面是一段,所以它应用了浅绿色背景。
到目前为止,我们使用的选择器为附加到 的目标元素设置了样式:has()
,例如<ul>
in ul:has(~ p)
。与常规选择器一样,我们的:has()
选择器可以扩展得更复杂,例如为不直接附加到选择:has()
器的元素设置样式条件。
在下面的选择器中,样式适用于作为 an本身具有 an作为相邻兄弟姐妹<p>
的兄弟姐妹的任何元素:<h2>
<h3>
h2:has(+ h3) ~ p
在下图中,<article>
显示了两个元素。在第二个中,段落的样式为淡绿色背景和增加的左边距,因为这些段落是 an 的兄弟姐妹,<h2>
后面跟着<h3>
。
:has()
注意:如果我们对可用的 CSS 选择器有很好的理解,我们使用起来会更成功。MDN 提供了选择器的简明概述,我已经编写了一个由两部分组成的关于选择器的系列文章,其中包含更多实际示例。
请记住,:has()
可以接受一个选择器列表,我们可以将其视为OR
条件。让我们选择一个段落,如果它包含<a>
_or_ <strong>
_or_ <em>
:
p:has(a, strong, em) {}
在下图中,有两个段落。因为第二段包含一个<strong>
元素,所以它具有浅绿色背景。
我们也可以链式:has()
选择器来创造AND
条件。在下面的复合选择器中,我们正在测试 an<img>
是 的第一个子节点<article>
,并且 the<article>
包含 an<h1>
后跟 an <h2>
:
article:has(> img:first-child):has(h1 + h2) {}
下图显示了三个<article>
元素。第二篇文章有浅绿色背景(以及其他样式),因为它包含作为第一个子项的图像和<h1>
后跟一个<h2>
。
最后可以预览下DEMO:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CSS has 知识 | Web前端之家www.jiangweishan.com</title> <style> #example-1 article:has(img) { background-color: palegreen; padding: 0 0 2rem; } #example-1 article:has(img) img { border-radius: 0.5rem 0.5rem 0 0; } #example-1 article:has(img) > *:not(img) { padding-inline: 1.5rem; } #example-2 article:has(> img) { background-color: palegreen; padding: 0 0 2rem; } #example-2 article:has(> img) img { border-radius: 0.5rem 0.5rem 0 0; } #example-2 article:has(> img) > *:not(img) { padding-inline: 1.5rem; } #example-3 h1:has(+ h2) { font-size: 3rem; background-color: palegreen; } #example-3 h1:has(+ h2) + h2 { -webkit-margin-before: 0.15em; margin-block-start: 0.15em; color: #797979; font-weight: 500; font-style: italic; } #example-4 ul:has(~ p) { background-color: palegreen; -webkit-margin-after: 2rem; margin-block-end: 2rem; } #example-5 h2:has(+ h3) ~ p { background-color: palegreen; -webkit-margin-start: 2em; margin-inline-start: 2em; } #example-6 p:has(a, strong, em) { background-color: palegreen; } #example-7 article:has(> img:first-child):has(h1 + h2) { background-color: palegreen; padding: 0 0 2rem; } #example-7 article:has(> img:first-child):has(h1 + h2) img { border-radius: 0.5rem 0.5rem 0 0; } #example-7 article:has(> img:first-child):has(h1 + h2) > *:not(img) { padding-inline: 1.5rem; } #example-7 article:has(> img:first-child):has(h1 + h2) :is(h1, h2) { font-weight: 500; } #example-7 article:has(> img:first-child):has(h1 + h2) h1 { font-family: Georgia, serif; font-size: 1.75rem; font-style: italic; } #example-7 article:has(> img:first-child):has(h1 + h2) h2 { -webkit-margin-before: 0.15em; margin-block-start: 0.15em; font-size: 1.25rem; } :root { --body-bg: whitesmoke; } body { font-size: 0.9rem; } [id] { display: grid; place-content: center; gap: 4vmax; min-height: 100vh; padding: 5vmax; } [id]:not(:first-child) { border-top: 1px dashed #797979; } [id] *:not([id] > h2, code, .columns) { outline: 1px dashed #797979; } [id] > h2 { text-align: center; } [data-tag] { position: relative; } [data-tag]::before { content: attr(data-tag); position: absolute; font-family: system-ui; font-style: normal; background-color: mediumvioletred; letter-spacing: 0.03em; padding: 0.25em; font-size: 1.05rem; font-weight: 500; color: #fff; top: 0; left: 0; transform: translate(-1ch, -33%); border-radius: 0.25rem; } h1 { font-size: 2rem; line-height: 1.1; } code { color: mediumvioletred; letter-spacing: -0.03em; } article { background-color: #fff; border-radius: 0.5rem; padding: 2rem; } article > img:first-child { width: 100%; -o-object-fit: cover; object-fit: cover; } article > * + *, article ul li + li { -webkit-margin-before: 1em; margin-block-start: 1em; } img { max-width: 100%; display: block; } .columns { width: min(80ch, 100vw - 2rem); display: grid; grid-template-columns: repeat(auto-fit, minmax(22ch, 1fr)); gap: 2vmax; align-items: start; } </style> </head> <body> <div id="example-1"> <h2><code>article:has(img)</code></h2> <div class="columns"> <article data-tag="article"> <h3>Lorem, ipsum dolor.</h3> <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p> </article> <article data-tag="article"> <img src='https://images.unsplash.com/photo-1554692901-e16f2046918a?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE2NzQwNzc0OTg&ixlib=rb-4.0.3&q=80&w=400' alt=''> <h3>Lorem, ipsum dolor.</h3> <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p> </article> <article data-tag="article"> <h3>Lorem, ipsum dolor.</h3> <p><img src='https://images.unsplash.com/photo-1638445533129-65aaf55fb94c?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE2NzQwNzc5MjE&ixlib=rb-4.0.3&q=80&w=20' alt=''> Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p> </article> </div> </div> <div id="example-2"> <h2><code>article:has(> img)</code></h2> <div class="columns"> <article data-tag="article"> <h3>Lorem, ipsum dolor.</h3> <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p> </article> <article data-tag="article"> <img src='https://images.unsplash.com/photo-1554692901-e16f2046918a?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE2NzQwNzc0OTg&ixlib=rb-4.0.3&q=80&w=400' alt=''> <h3>Lorem, ipsum dolor.</h3> <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p> </article> <article data-tag="article"> <h3>Lorem, ipsum dolor.</h3> <p><img src='https://images.unsplash.com/photo-1638445533129-65aaf55fb94c?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE2NzQwNzc5MjE&ixlib=rb-4.0.3&q=80&w=20' alt=''> Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p> </article> </div> </div> <div id="example-3"> <h2><code>h1:has(+ h2)</code></h2> <article> <h1 data-tag="h1">Lorem, ipsum dolor.</h1> <h2>Sit amet consectetur adipisicing elit.</h2> <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati odit reprehenderit culpa.</p> </article> <article> <h1 data-tag="h1">Lorem, ipsum dolor.</h1> <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati odit reprehenderit culpa.</p> </article> </div> <div id="example-4"> <h2><code>ul:has(~ p)</code></h2> <div class="columns"> <article> <ul data-tag="ul"> <li>Lorem, ipsum dolor.</li> <li>Fugiat, officiis sint!</li> <li>Sit, facere ratione!</li> </ul> </article> <article> <ul data-tag="ul"> <li>Lorem, ipsum dolor.</li> <li>Labore, a blanditiis!</li> <li>Tempora, amet consectetur.</li> </ul> <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit.</p> </article> </div> </div> <div id="example-5"> <h2><code>h2:has(+ h3) ~ p</code></h2> <div class="columns"> <article> <h2 data-tag="h2">Lorem, ipsum dolor.</h2> <p data-tag="p">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima placeat quo omnis.</p> <p data-tag="p">Expedita est consectetur pariatur in, sint maiores molestiae temporibus vitae deleniti recusandae.</p> </article> <article> <h2 data-tag="h2">Sit amet consectetur</h2> <h3 data-tag="h3">Porro delectus maxime ea</h3> <p data-tag="p">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Quod rerum quo nam.</p> <p data-tag="p">Corrupti incidunt similique unde iste alias nostrum sit quae natus pariatur impedit?</p> </article> </div> </div> <div id="example-6"> <h2><code>p:has(a, strong, em)</code></h2> <div class="columns"> <article> <p data-tag="p">Lorem ipsum dolor sit amet consectetur adipisicing elit. Neque non corporis nesciunt mollitia natus. Harum.</p> </article> <article> <p data-tag="p">Eaque voluptatum <strong>soluta sit ipsam</strong> nihil vel optio ratione numquam magnam. Beatae amet velit odio?</p> </article> </div> </div> <div id="example-7"> <h2><code>article:has(> img:first-child):has(h1 + h2)</code></h2> <div class="columns"> <article data-tag="article"> <h1 data-tag="h1">Lorem, ipsum dolor.</h1> <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p> </article> <article data-tag="article"> <img src='https://images.unsplash.com/photo-1554692901-e16f2046918a?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE2NzQwNzc0OTg&ixlib=rb-4.0.3&q=80&w=400' alt=''> <h1 data-tag="h1">Lorem, ipsum dolor.</h1> <h2 data-tag="h2">Consectetur adipisicing elit</h2> <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p> </article> <article data-tag="article"> <img src='https://images.unsplash.com/photo-1526137966266-60618b40bcd4?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwzMjM4NDZ8MHwxfHJhbmRvbXx8fHx8fHx8fDE2NzQwODM1Nzc&ixlib=rb-4.0.3&q=80&w=400' alt=''> <h1 data-tag="h1">Lorem, ipsum dolor.</h1> <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p> </article> </div> </div> </body> </html>