CSS结构伪类选择器

363 阅读5分钟

CSS中的结构伪类选择器

结构伪类选择器主要根据文档结构来选择元素, 常用于根据父级选择器里面的子元素。合理使用结构伪类选择器,可以节省类名的定义,减少代码量。

结构伪类选择器的用法

选择符简介
E:first-child匹配父元素中的第一个子元素E
E:last-child匹配父元素中最后一个E元素
E:nth-child(n)匹配父元素中的第n个子元素E
E:first-of-type指定类型E的第一个
E:last-of-type指定类型E的最后一个
E:nth-of-type(n)指定类型E的第n个

选择器中n值

  • n可以是数字,关键字和公式
  • 如果是数字,就是选择第n个子元素,里面数字从1开始
  • n可以是关键字:even偶数,odd奇数
  • n可以是公式:常见的公式如下(如果n是公式,则从0开始计算,但是第0个元素或者超出了元素的个数会被忽略)
公式取值
2n偶数
2n+1奇数
5n5 1015 ...
n+5从第5个开始(包含第五个)到最后
-n+5前5个(包含第5个)...

用法详解

直入主题,我们将常用的结构伪类选择器分为两类:

  • 选择兄弟元素
    • :first-child
    • :last-child
    • :nth-child(n)
  • 选择同类型兄弟元素
    • :first-of-type
    • :last-of-type
    • :nth-of-type(n)

这两者的区别主要在于:前者是对父元素里面的所有孩子进行排序选择(序号固定),先找到第n个孩子,再看是否与该元素类型匹配;后者是对父元素里面指定的子元素(同类型)进行排序选择,先去匹配元素类型,再根据元素找第n个孩子

下面举个例子。

假设盒子结构如下:

<div class="father">
       <div>第一个div</div>
       <p>第一个p</p>
       <div>第二个div</div>
       <h3>第一个h3</h3>
       <p>第二个p</p>
       <h3>第二个h3</h3>
</div>

这里,我要去找第一个div和第二个div。先直接使用:first-child:last-child,看看能否正常选中。

.father div:first-child {
      background-color: red;
}
.father div:last-child {
      background-color: yellow;
 }

image-20230509171225021.png

结果并不能找到第二个div,我们放弃:last-child写法,使用:nth-child(3)来看能否选中。

.father div:first-child {
     background-color: red;
}
.father div:nth-child(3) {
     background-color: aqua;
}

image-20230509171712015.png

正确找到了第二个div。那么为什么:last-child写法找不到,使用:nth-child(3)就能正确找到了呢?

原因如下:

  • 沿用上文的解释:在进行选择前,会把父元素里面的所有孩子进行排序选择(div,p,h3全部进行排序,序号固定),先找到第n个孩子,再看是否与该元素类型匹配。
  • :last-child找不到的原因是因为,这里选择的是序号为最后的孩子,也就是上图中的第二个h3,选中后再进行类型匹配,发现最后一个元素类型为h3与div类型不同,因此没有找到。同理,:nth-child(3)之所以能找到,是当选中第三个孩子后,进行元素类型匹配,同为div,因而正确选中。

我们在看上文的第二句话就好理解了:“选择前对父元素里面指定的子元素(同类型)进行排序选择,先去匹配元素类型,再根据元素找第n个孩子”。

因此,对于刚刚的情形,我们可以直接使用:first-of-type:last-of-type或者:nth-of-type(1):nth-of-type(2)更直观的选择第一个div和第二个div。

.father div:first-of-type {
      background-color: blue;
}
.father div:last-of-type {
      background-color: green;
}

image-20230509181356806.png

总结:当父元素里面的子元素类型统一时,:nth-child(n):nth-of-type(n)效果上没有区别,推荐使用前者;当父元素里面的子元素类型不统一时,使用:nth-of-type(n)

不常用用法补充

除去直接写标签名+伪类选择器的形式,还可以使用类名+伪类选择器。这种方法不常用,但也存在,某种程度上不太好理解,特在此补充,供大家参考。

  • 当我们使用类 :nth-child(n)时,依旧是将父元素的子代元素标签排序,然后进行类名匹配,与直接使用标签类似。
  • 当我们使用类 :nth-of-type(n)时,先是找不同类型满足条件的标签进行分类,随后排序,最终进行类名匹配,这点与直接使用标签有略微差别,下面有个例子能很好诠释这个情况(实际开发中,不这么用,仅供参考和理解)。
<p class="banner">p-banner</p>
<div class="item">div-item</div>
<div class="title">div-title</div>
<div class="banner">div-banner1</div>
<div class="banner">div-banner2</div>
<p class="banner">p-banner1</p>
<p class="banner">p-banner2</p>
.banner:first-of-type {
     background-color: aqua;
}
.banner:last-of-type {
     background-color: blue;
}

image-20230509221146367.png

首先,在选择前会进行分类,p标签为一类,div标签为一类,随后分别进行排序,序号独自计算。

对于.banner:first-of-type:p-banner是p标签一类的第一个元素并且类名匹配,因此会天蓝色高亮;div标签的第一个元素类名为item,不与banner匹配,因此不会被选中,因而只有p-banner高亮。

对于.banner:last-of-type:原理与上面类似,会选择两类标签排序最后的一个元素,并且他们的类名也匹配,因此div-banner2和p-banner2变成蓝色高亮。