×

CSS基础拓展:解析CSS 中的 :has() 选择器

作者:Terry2023.05.05来源:Web前端之家浏览:6682评论:0
关键词:csshtml

作为“父选择器”的先驱,:has()伪类的范围远比仅仅为元素的祖先设置样式大得多。凭借其在 Safari 15.4+ 和 Chromium 105+ 中的可用性,以及在 Firefox 中的标志,现在是您熟悉:has()其用例的好时机。

作为一个伪类,它的基本功能:has()是设置它所附加的元素的样式——也就是所谓的“目标”元素。这类似于其他伪类,如:hoveror :activea:hover旨在为<a>处于活动状态的元素设置样式。

然而,:has()也类似于:is():where(), 和:not(),因为它接受括号内的相对选择器列表。这允许:has()创建复杂的标准来测试,使其成为一个非常强大的选择器。

为了感受它是如何:has()工作的,让我们看一个如何应用它的例子。在下面的选择器中,我们测试一个<article>元素是否有一个<img>子元素:

article:has(img) {}

此选择器的可能结果如下图所示。显示了三个文章元素,其中两个包含图像,并且都具有浅绿色背景和与没有图像的元素不同的填充。

image.png


只要<img>元素存在于该<article>元素的任何位置,上面的选择器就会应用——无论是作为直接子元素还是作为其他嵌套元素的后代。

如果我们想确保规则仅适用于元素<img>的直接(非嵌套)子元素<article>,我们还可以包含子组合器:

article:has(> img) {}

此更改的结果如下图所示。显示了相同的三张卡片,但这次只有图像是 的直接子代的那一张<article>具有浅绿色背景和填充。

image.png

在这两个选择器中,我们定义的样式都应用于目标元素,即<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>应用了浅绿色背景。

image.png

使用通用兄弟组合器 ( ~),我们可以检查特定元素是否是目标后面任何位置的兄弟。在这里,我们正在检查某处是否有一个<p>元素作为 的兄弟元素<ul>

ul:has(~ p) {}

下图显示了两个<article>元素,每个元素都包含一个无序列表。第二篇文章的列表后面是一段,所以它应用了浅绿色背景。

image.png

到目前为止,我们使用的选择器为附加到 的目标元素设置了样式:has(),例如<ul>in ul:has(~ p)。与常规选择器一样,我们的:has()选择器可以扩展得更复杂,例如为不直接附加到选择:has()器的元素设置样式条件。

在下面的选择器中,样式适用于作为 an本身具有 an作为相邻兄弟姐妹<p>的兄弟姐妹的任何元素:<h2><h3>

h2:has(+ h3) ~ p

在下图中,<article>显示了两个元素。在第二个中,段落的样式为淡绿色背景和增加的左边距,因为这些段落是 an 的兄弟姐妹,<h2>后面跟着<h3>

image.png

:has()注意:如果我们对可用的 CSS 选择器有很好的理解,我们使用起来会更成功。MDN 提供了选择器的简明概述,我已经编写了一个由两部分组成的关于选择器的系列文章,其中包含更多实际示例。

请记住,:has()可以接受一个选择器列表,我们可以将其视为OR条件。让我们选择一个段落,如果它包含<a>_or_ <strong>_or_ <em>

p:has(a, strong, em) {}

在下图中,有两个段落。因为第二段包含一个<strong>元素,所以它具有浅绿色背景。

image.png

我们也可以链式:has()选择器来创造AND条件。在下面的复合选择器中,我们正在测试 an<img>是 的第一个子节点<article>,并且 the<article>包含 an<h1>后跟 an <h2>

article:has(> img:first-child):has(h1 + h2) {}

下图显示了三个<article>元素。第二篇文章有浅绿色背景(以及其他样式),因为它包含作为第一个子项的图像和<h1>后跟一个<h2>

image.png

最后可以预览下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>




您的支持是我们创作的动力!
温馨提示:本文作者系Terry ,经Web前端之家编辑修改或补充,转载请注明出处和本文链接:
https://jiangweishan.com/article/htmlcss20230505.html

网友评论文明上网理性发言 已有0人参与

发表评论: