We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
今天群里讨论了一个非常有意思与 CSS 选择器相关的题目。题目如下:
假设我们如下的 HTML 结构:
<div class="box"> <p class="aa">aaaaaaaaaaaa</p> <p class="bb">bbbbbbbbbbbb</p> <p class="cc">cccccccccccc</p> <p class="aa">aaaaaaaaaaaa</p> <p class="bb">bbbbbbbbbbbb</p> <p class="cc">cccccccccccc</p> <p class="aa">aaaaaaaaaaaa</p> <p class="bb">bbbbbbbbbbbb</p> <p class="cc">cccccccccccc</p> </div>
效果如下:
如何在不添加类名的情况下,快速的选取第一个 class 为 .cc 的元素?
.cc
当然,上面的结构示意图只是一种可能的情况,这里想表述的场景的意思是:
<p>
.bb + .cc
.bb
基于上述的限定条件,你可以暂停阅读,思考 20 秒,可能的方式有哪些?
一般而言,比较容易想到的,肯定是首先使用 :nth-child 和 :nth-of-type 伪类选择器进行尝试。
:nth-child
:nth-of-type
但是,遗憾的是,这两个选择器都无法做到在上述结构下,成功选取第一个 .cc 元素。
代码如下:
.box .cc:nth-child(1) { color: red; font-size: 24px; }
或者
.box .cc:nth-of-type(1) { color: red;.box .cc:nth-child(1) { color: red; font-size: 24px; }
也就是说,上述两种方式,都是不行的。简单解释一下:
:nth-child()
这里最重要的是,它是根据父元素内的所有兄弟元素的位置来选择子元素,而我们无法得知在实际业务场景下,第一个 .cc 到底处于第几个索引。因此,这个选择器明显没法胜任。
非常重要的一点是,使用此选择器无法选择基于相同类名的元素的位置,来匹配元素。
什么意思呢?
如果我们把上述 DEMO 改造,改造成这样:
<div class="box"> <p class="aa">aaaaaaaaaaaa</p> <span class="bb">bbbbbbbbbbbb</span> <div class="cc">cccccccccccc</div> <p class="aa">aaaaaaaaaaaa</p> <span class="bb">bbbbbbbbbbbb</span> <div class="cc">cccccccccccc</div> <p class="aa">aaaaaaaaaaaa</p> <span class="bb">bbbbbbbbbbbb</span> <div class="cc">cccccccccccc</div> </div>
再基于上述结构下,选择第一个 class 为 .cc 的元素,就可以利用 :nth-of-type 实现。因为,所有的 .cc 都是 div 元素,且没有其它 div 元素:
div
.box div:nth-of-type(1) { color: red; font-size: 24px; }
当然,实际情况远没有如此乐观。在所有子元素标签情况无法确定的情况下,基于上述讨论,使用 :nth-child 或者 :nth-of-type 都不可行。还有什么办法呢?
按照上面说的,如果存在一个伪类 :nth-of-class,可以实现,基于相同类名的元素的位置,来匹配元素,那么问题就解决了。
:nth-of-class
但是实际情况是,目前 CSS 规范仍未支持 :nth-of-class 伪类选择器。
我们必须另辟蹊径。
好,现在我们换个思路,如果要我们选择,非第一个 class 为 .cc 的 .cc 元素,可以怎么实现呢?
可以利用 ~ 后续兄弟选择器实现:
~
.box .cc ~ .cc { color: red; font-size: 24px; }
成功了!此时,我们只需要基于上述结果,取反即可。在现代 CSS 中,我们可以利用 :not() 伪类实现。
:not()
:not() 伪类::not() CSS 伪类用来匹配不符合一组选择器的元素。由于它的作用是防止特定的元素被选中,它也被称为反选伪类(negation pseudo-class)。
改造一下上述的代码:
.box .cc:not(.cc ~ .cc) { color: red; font-size: 24px; }
这样,我们就成功的选取到了第一个 .cc 元素。
还有办法吗?
是的,在现代 CSS 中,:nth-child() 提供了一种更为强大的方式供我们使用。
从 Chrome 111,:nth-child() 提供了一种更为强大的特性,让我们能够方便的实现上述的效果,这种语法就是 :nth-child(1 of .foo)。
:nth-child(1 of .foo)
看看 [CanIUse - :nth-child(1 of .foo)(https://caniuse.com/?search=%3Anth-child):
我们能够通过 :nth-child(1 of .foo) 这个特性,间接实现 :nth-of-class 的效果:
.box .cc:nth-child(1 of .cc) { color: red; font-size: 24px; }
当然,利用这个特性,可以快速的选择任意 index 的 .cc 元素:
譬如第二个:
.box .cc:nth-child(2 of .cc) { color: red; font-size: 24px; }
完整的 DEMO,你可以戳这里:CodePen Demo -- 选择子元素下第一个类名为 xx 的元素
此功能由规范 Selectors Level 4 - :nth-child() pseudo-class 提出,感兴趣的可以看看规范原文定义。
of S
在掌握 of S 这个规则之后,我们就可以轻松的 Cover 非常多在之前选取起来非常困难的一些场景。
我们举几个例子一起看看,假设我们有如下的结构:
<div class="g-container"> <div class="g-item-triangle"></div> <div class="g-item-star"></div> <div class="g-item-hexagon"></div> <div class="g-item-triangle"></div> <div class="g-item-star"></div> <div class="g-item-hexagon"></div> <div class="g-item-star"></div> <div class="g-item-hexagon"></div> <div class="g-item-triangle"></div> <div class="g-item-star"></div> <div class="g-item-hexagon"></div> <div class="g-item-triangle"></div> <div class="g-item-triangle"></div> <div class="g-item-star"></div> <div class="g-item-hexagon"></div> <div class="g-item-triangle"></div> <div class="g-item-star"></div> <div class="g-item-hexagon"></div> </div>
简单的 CSS 代码如下:
.g-container { position: relative; width: 800px; height: 300px; display: flex; justify-content: space-between; flex-wrap: wrap; & > div { width: 120px; height: 120px; flex-shrink: 0; background: #fc0; } .g-item-triangle { clip-path: polygon(50% 0, 100% 100%, 0 100%); } .g-item-star { clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%); } .g-item-hexagon { clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%); } }
即可得到如下结构:
由于上述的三角形 .g-item-triangle、星形 .g-item-star以及六边形 .g-item-hexagon 都在同一个父容器下,并且它们都是使用 div 表示,只是有不同的 class 进行表示。
.g-item-triangle
.g-item-star
.g-item-hexagon
class
首先,我们来看看,我们的诉求是,如何选取所有元素下的第二个六边形元素?
你可能认为可以使用如下代码?
.g-item-hexagon:nth-child(2) { background: #f00; }
按照我们上面文章提到的,这显然是选不到的。
但是如果你了解了 :nth-child 的 of S 特性,这个问题就非常简单了:
:nth-child(2 of .g-item-hexagon) { background: #f00; }
这样,成功选取到了所有元素下的第二个六边形元素:
继续,此外,of S 规范还支持 2n、even、odd 这样匹配规则。
2n
even
odd
因此,当我们想选取偶数位数的三角形时,可以写成:
:nth-child(2n of .g-item-star) { background: #f00; } // OR, 下述写法也可以 :nth-child(even of .g-item-star) { background: #f00; }
最后,of S 规则还可以在内部再使用 :not() 伪类,实现某些特定元素的剔除。
譬如,我们希望去掉所有元素内部的星星元素,在剩下的元素中,再选取所有奇数序号的元素。
听起来有点麻烦,写起来很简单:
:nth-child(2n+1 of :not(.g-item-star)) { background: #f00; }
此时,效果如下:
这里应用 :not() 规则后,相当于把 .g-item-star 去掉,剩余的 .g-item-hexagon 和 .g-item-triangle 当成一个新的整体,应用 of S 前的规则。需要好好理解一下。
完整的 DEMO,你可以戳这里:CodePen Demo -- nth-child of S rule Demo
好了,本文到此结束,一个非常有意思的现代选择器功能,你学会了吗?希望本文对你有所帮助 :)
想 Get 到最有意思的 CSS 资讯,千万不要错过我的公众号 -- iCSS前端趣闻 😄
更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。
如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。
The text was updated successfully, but these errors were encountered:
这个会选取每个元素下的第一个 有没有办法选区整个document下的第一个 更进一步,限定到某个范围内的第一个
Sorry, something went wrong.
No branches or pull requests
今天群里讨论了一个非常有意思与 CSS 选择器相关的题目。题目如下:
假设我们如下的 HTML 结构:
效果如下:
如何在不添加类名的情况下,快速的选取第一个 class 为
.cc
的元素?当然,上面的结构示意图只是一种可能的情况,这里想表述的场景的意思是:
.cc
元素,在其父元素下,存在多个.cc
,所以需要精准定位第一个;.cc
元素一定不是其所有兄弟元素中的第一个;<p>
元素或者某个同类标签.bb + .cc
的方式直接进行选取,因为第一个.cc
元素的上一个元素不一定是.bb
,可以是其他任何元素;基于上述的限定条件,你可以暂停阅读,思考 20 秒,可能的方式有哪些?
使用 :nth-child 或者 :nth-of-type
一般而言,比较容易想到的,肯定是首先使用
:nth-child
和:nth-of-type
伪类选择器进行尝试。但是,遗憾的是,这两个选择器都无法做到在上述结构下,成功选取第一个
.cc
元素。代码如下:
或者
也就是说,上述两种方式,都是不行的。简单解释一下:
:nth-child
而言,:nth-child()
伪类根据元素在父元素的子元素列表中的索引来选择元素。最为核心的是,选择器,它是根据父元素内的所有兄弟元素的位置来选择子元素。这里最重要的是,它是根据父元素内的所有兄弟元素的位置来选择子元素,而我们无法得知在实际业务场景下,第一个
.cc
到底处于第几个索引。因此,这个选择器明显没法胜任。:nth-of-type
而言,基于相同类型(标签名称)的兄弟元素中的位置来匹配元素。非常重要的一点是,使用此选择器无法选择基于相同类名的元素的位置,来匹配元素。
什么意思呢?
如果我们把上述 DEMO 改造,改造成这样:
再基于上述结构下,选择第一个 class 为
.cc
的元素,就可以利用:nth-of-type
实现。因为,所有的.cc
都是 div 元素,且没有其它div
元素:效果如下:
当然,实际情况远没有如此乐观。在所有子元素标签情况无法确定的情况下,基于上述讨论,使用
:nth-child
或者:nth-of-type
都不可行。还有什么办法呢?使用 :nth-of-class 伪类?
按照上面说的,如果存在一个伪类
:nth-of-class
,可以实现,基于相同类名的元素的位置,来匹配元素,那么问题就解决了。但是实际情况是,目前 CSS 规范仍未支持
:nth-of-class
伪类选择器。我们必须另辟蹊径。
巧用 :has() 与后代选择器 ~
好,现在我们换个思路,如果要我们选择,非第一个 class 为
.cc
的.cc
元素,可以怎么实现呢?可以利用
~
后续兄弟选择器实现:效果如下:
成功了!此时,我们只需要基于上述结果,取反即可。在现代 CSS 中,我们可以利用
:not()
伪类实现。改造一下上述的代码:
这样,我们就成功的选取到了第一个
.cc
元素。还有办法吗?
是的,在现代 CSS 中,
:nth-child()
提供了一种更为强大的方式供我们使用。使用 :nth-child 伪类的现代特性
从 Chrome 111,
:nth-child()
提供了一种更为强大的特性,让我们能够方便的实现上述的效果,这种语法就是:nth-child(1 of .foo)
。看看 [CanIUse - :nth-child(1 of .foo)(https://caniuse.com/?search=%3Anth-child):
我们能够通过
:nth-child(1 of .foo)
这个特性,间接实现:nth-of-class
的效果:效果如下:
当然,利用这个特性,可以快速的选择任意 index 的
.cc
元素:譬如第二个:
效果如下:
完整的 DEMO,你可以戳这里:CodePen Demo -- 选择子元素下第一个类名为 xx 的元素
此功能由规范 Selectors Level 4 - :nth-child() pseudo-class 提出,感兴趣的可以看看规范原文定义。
进阶理解新特性
of S
规则及实际应用演示在掌握
of S
这个规则之后,我们就可以轻松的 Cover 非常多在之前选取起来非常困难的一些场景。我们举几个例子一起看看,假设我们有如下的结构:
简单的 CSS 代码如下:
即可得到如下结构:
由于上述的三角形
.g-item-triangle
、星形.g-item-star
以及六边形.g-item-hexagon
都在同一个父容器下,并且它们都是使用div
表示,只是有不同的class
进行表示。1.选取第二个六边形元素
首先,我们来看看,我们的诉求是,如何选取所有元素下的第二个六边形元素?
你可能认为可以使用如下代码?
按照我们上面文章提到的,这显然是选不到的。
但是如果你了解了
:nth-child
的of S
特性,这个问题就非常简单了:这样,成功选取到了所有元素下的第二个六边形元素:
2. 选取偶数位数的三角形
继续,此外,
of S
规范还支持2n
、even
、odd
这样匹配规则。因此,当我们想选取偶数位数的三角形时,可以写成:
效果如下:
3. 选取去掉星形元素后的所有奇数个数元素
最后,
of S
规则还可以在内部再使用:not()
伪类,实现某些特定元素的剔除。譬如,我们希望去掉所有元素内部的星星元素,在剩下的元素中,再选取所有奇数序号的元素。
听起来有点麻烦,写起来很简单:
此时,效果如下:
这里应用
:not()
规则后,相当于把.g-item-star
去掉,剩余的.g-item-hexagon
和.g-item-triangle
当成一个新的整体,应用of S
前的规则。需要好好理解一下。完整的 DEMO,你可以戳这里:CodePen Demo -- nth-child of S rule Demo
最后
好了,本文到此结束,一个非常有意思的现代选择器功能,你学会了吗?希望本文对你有所帮助 :)
想 Get 到最有意思的 CSS 资讯,千万不要错过我的公众号 -- iCSS前端趣闻 😄
更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。
如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。
The text was updated successfully, but these errors were encountered: