last-of-type 选择器的发现

:last-of-type 是CSS3新增的选择器,表示指定元素名称位于父元素的字元素列表中的最后一个元素。简而言之就是最后的一个元素。在W3C的说明和MDN的说明页面上都是以元素作为前置选择,但其实:last-of-type也可以作为样式名的伪类选择器。

MDN例子

1
2
3
p em:last-of-type {
color: lime;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<p>
<em>I'm not lime :(</em>
<strong>I'm not lime :(</strong>
<em>I'm lime :D</em>
<strong>I'm also not lime :(</strong>
</p>

<p>
<em>I'm not lime :(</em>
<span><em>I am lime!</em></span>
<strong>I'm not lime :(</strong>
<em>I'm lime :D</em>
<span><em>I am also lime!</em> <strike> I'm not lime </strike></span>
<strong>I'm also not lime :(</strong>
</p>

结果

I’m not lime :( I’m not lime :( I’m lime :D I’m also not lime :(

I’m not lime :( I am lime! I’m not lime :( I’m lime :D I am also lime! I’m not lime I’m also not lime :(

如果按照上面的代码理解,所有p元素下的最后一个em元素的字体将会是lime颜色。

样式名之后的last-of-type

看完MDN的说法应该也对last-of-type的选择器有了一定的了解,当所有比较官方的例子中都以元素作为前置的选择器那么如果以样式名作为前置选择器会怎么样呢?

是否有效?

1
2
3
4
5
6
7
.wrap .a:last-of-type{
color: lime;
}

.wrap .b:last-of-type{
color: red;
}
1
2
3
4
5
6
7
<div class="wrap">
<p class="a">我是一段文字</p>
<p class="b">我是一段文字</p>
<p class="c">我是一段文字</p>
<p class="b">我是一段文字</p>
<p class="a">我是一段文字</p>
</div>

结果

我是一段文字a

我是一段文字b

我是一段文字c

我是一段文字b

我是一段文字a

总结

看到执行结果可能会有读者感到很疑惑,为何.wrap .a:last-of-type选择符是有效果的而.wrap .b:last-of-type却失效了呢?

首先可以肯定的是:last-of-type是支持样式名选择器作为前置的,但只是要符合以下条件:

样式名选择器所选择的元素为当前父元素的子元素列表中的最后一个,也就是说不但要符合选择器.b并且要符合${element}:last-of-type。在

针对上面HTML的结构来生成一个表达式的话,
.wrap .b:last-of-type === .wrap .b && p:last-of-type

如果把上面的HTMl代码改成如下:

1
2
3
4
5
6
7
<div class="wrap">
<p class="a">我是一段文字</p>
<p class="b">我是一段文字</p>
<p class="c">我是一段文字</p>
<div class="b">我是一段文字</div>
<p class="a">我是一段文字</p>
</div>

我是一段文字a

我是一段文字b

我是一段文字c

我是一段文字b

我是一段文字a

按上述修改后,最后一个.b把元素修改成div则符合了${element}:last-of-type这一个要求,所以就生效了。