你可能不清楚的 CSS 选择器用法(一)

1,148 阅读6分钟
原文链接: github.com

这是一篇由一个 CSS 选择器引发的文章,讲真,从来没想过会写一篇关于 CSS 选择器的文章。

事先声明,这篇文章是对一些基础的回顾,没有什么新东西或者黑科技。
如果你早已将这些 CSS 基础烂熟于胸,大可直接 Ctrl + w。
如果你跟我一样对这些基础有些遗忘,那么可以尝试看下去。

事情的经过是这样的......

那是一个月黑风高的夜晚,我和同事一边愉快地加着班,一边悲愤地打着农药。趁着被敌方后羿shutdown的间隙,我花了 20 秒敲下了一行代码,等待页面热更新,查看效果,perfect!一切正常!

然鹅,正当我快要复活的时候,列表也滚到底了,卧槽!!最后一个 Item 样式出现了问题,但是时间已经来不及,快要复活了......以后可以写一篇博客叫《论敌方打野与我方打野》。

虽然我只花了一分钟就换了个方式来解决这个问题,但彻底把原来的问题搞明白却花了我差不多一个小时。

先给大家重现一下问题:

之前正常运行的代码

   <div class="list">
                <div class="item">我是第一个item</div>
                <div class="item">我是第二个item</div>
                <div class="item">我是第三个item</div>
                <div class="item">我是第四个item</div>
                <div class="item">我是第五个item</div>
        </div>
   .list {
                padding: 15px;
                background-color: #eee;
        }
        .item {
                margin-bottom: 15px;
                border-radius: 4px;
                background-color: #fff;
        }
        .item:last-child {
                margin-bottom: 50px;
        }

有问题的代码

   <div class="list">
                <div class="item">我是第一个item</div>
                <div class="item">我是第二个item</div>
                <div class="item">我是第三个item</div>
                <div class="item">我是第四个item</div>
                <div class="item">我是第五个item</div>
                <div class="dialog">......</div>
        </div>
   .list {
                padding: 15px;
                background-color: #eee;
        }
        .item {
                margin-bottom: 15px;
                border-radius: 4px;
                background-color: #fff;
        }
        .item:last-child {
                margin-bottom: 50px;
        }

发现问题在哪了吗?
如果你一眼看出问题所在,并确切的知道原因,那么恭喜你,CSS 基础还是挺扎实的。
如果你发现了问题但不确定原因或者压根都没找到问题,那么也同样恭喜你,至少看见了这篇文章。

:last-child

通常用法:element:last-child

匹配 element 父元素及其父元素的子元素,中的最后一个 element 子元素。

注意:这里的 element 元素必须是其父元素下 所有元素 的最后一个子元素才有效。

例子:

   <div class="list">
                <div class="item">我是第一个item</div>
                <div class="item">我是第二个item</div>
                <div class="item">我是第三个item</div>
                <div class="box">
                        <div class="item">穿插一个盒子item</div>
                        <div class="item">穿插两个盒子item</div>
                        <div class="item">穿插三个盒子item</div>
                </div>
                <div class="item">我是第四个item</div>
                <div class="item">我是最后一个item,但不是最后一个子元素</div>
                <div class="haha">我才是最后一个子元素</div>
        </div>
   .list {
                padding: 15px;
                background-color: #eee;
        }
        .item {
                margin-bottom: 15px;
                border-radius: 4px;
                background-color: green;
        }
        .item:last-child {
                background-color: red;
        }
        .box {
                margin-left: 50px;
        }
        .haha {
                background-color: yellow;
        }

image

:first-child 选择器与它用法一样

:last-of-type

通常用法:element:last-of-type

匹配 element 父元素下及其父元素的子元素,中的最后一个 element 子元素。

注意:这里的 element 元素只要是其父元素下的 所有 element 元素 中的最后一个就可以。

所以看到这里,你是不是会以为下面这段代码:

   <div class="list">
                <div class="item">我是第一个item</div>
                <div class="item">我是第二个item</div>
                <div class="item">我是第三个item</div>
                <div class="box">
                        <div class="item">穿插一个盒子item</div>
                        <div class="item">穿插两个盒子item</div>
                        <div class="item">穿插三个盒子item</div>
                </div>
                <div class="item">我是第四个item</div>
                <div class="item">我是最后一个item,但不是最后一个子元素</div>
                <div class="haha">我才是最后一个子元素</div>
        </div>
   .list {
                padding: 15px;
                background-color: #eee;
        }
        .item {
                margin-bottom: 15px;
                border-radius: 4px;
                background-color: green;
        }
        .list .item:last-of-type {
                background-color: red;
        }
        .box {
                margin-left: 50px;
        }
        .haha {
                background-color: yellow;
        }

它的结果会是这样:

image

大错特错!

它的结果其实是这样:

image

让我们把上面 class="item"div 标签换成 p 标签,那么结果就是

image

image

明明是同样的 HTML 结构和 CSS 样式,为什么就换了一个标签类型,结果就不一样了呢?

我在规范文档里发现了这样两句话:

Pseudo-classes are allowed in all sequences of simple selectors contained in a selector. Pseudo-classes 
are allowed anywhere in sequences of simple selectors, after the leading type selector or universal 
selector (possibly omitted).
:first-of-type pseudo-class
Same as :nth-of-type(1). The :first-of-type pseudo-class represents an element that is the first sibling of its type.

其大致意思是:

在一个选择器中,所有包含[简单选择器](https://drafts.csswg.org/selectors-3/#simple-selectors)的序列中都允许伪类。在简单选择器序列中,伪类可以放在任何地方,在主类型选择器后或者通配符选择器后(可能省略)。
:first-of-type 伪类
等同于 :nth-of-type(1)。 :first-of-type 伪类表示它这种类型的第一个兄弟元素。

不知道你是什么赶脚,反正我是

image

文字的表达和理解真的不是一件简单的事,所以我也只能大概的总结一下,意思就是:

:last-of-type 这样的伪类,是可以跟在一个任意简单选择器后的,但除了要匹配这个简单选择器,同时还要匹配这个简单选择器的元素类型,也就是元素标签。

talk is cheap,show you the code:

   <div class="list">
                <p class="item">我是第一个p标签 .item</p>
                <p class="item">我是第二个p标签 .item</p>
                <p class="item">我是第三个p标签 .item</p>
                <div class="box">
                        <p class="item">穿插一个盒子p标签 .item</p>
                        <p class="item">穿插两个盒子p标签 .item</p>
                        <p class="item">穿插三个盒子p标签 .item</p>
                </div>
                <p class="item">我是第四个p标签 .item</p>
                <p class="item">我是最后一个p标签 .item</p>
                <div class="item">我是最后一个 .item,但不是最后一个div元素</div>
                <div class="haha">我才是最后一个div元素</div>
        </div>
   .list {
                padding: 15px;
                background-color: #eee;
        }
        .item {
                margin-bottom: 15px;
                border-radius: 4px;
                background-color: green;
        }
        .list .item:last-of-type {
                background-color: red;
        }
        .box {
                margin-left: 50px;
        }
        .haha {
                background-color: yellow;
        }

image

总结

这一篇写完,连我自己都有些晕,所以大家还是要仔细看看代码,挨个敲一敲,然后再好好体会。