CSS可以检测元素包含的子级数目吗?


303

我可能在回答自己的问题,但我很好奇。

我知道CSS可以选择父级的单个子级,但是如果其父级有一定数量的子级,则可以支持样式化容器的子级。

例如

container:children(8) {
  // style the parent this way if there are 8 children
}

我知道这听起来很奇怪,但是我的经理要求我检查一下,自己还没有找到任何东西,所以我决定在结束搜索之前转向SO。


2
数量查询SCSS Mixin:codepen.io/jakob-e/pen/wgGpeP
Jakob E

Answers:


694

澄清:

由于原始问题的先前措辞,一些SO公民提出了对此答案可能产生误导的担忧。请注意,在CSS3中,样式无法基于其具有的子代数应用于父节点。但是,可以根据子节点具有的兄弟节点数将样式应用于子节点。


原始答案:

令人难以置信的是,现在这完全可以在CSS3中实现。

/* one item */
li:first-child:nth-last-child(1) {
/* -or- li:only-child { */
    width: 100%;
}

/* two items */
li:first-child:nth-last-child(2),
li:first-child:nth-last-child(2) ~ li {
    width: 50%;
}

/* three items */
li:first-child:nth-last-child(3),
li:first-child:nth-last-child(3) ~ li {
    width: 33.3333%;
}

/* four items */
li:first-child:nth-last-child(4),
li:first-child:nth-last-child(4) ~ li {
    width: 25%;
}

诀窍是在第一个孩子也是第n个孩子时选择第一个孩子。这有效地根据兄弟姐妹的数量进行选择。

这种技术值得称赞的是AndréLuís(已发现)和Lea Verou(已提炼)。

您不只是喜欢CSS3吗?😄

CodePen示例:

资料来源:


7
非常便利。我编写了一个使用此技术的SASS mixin:codepen.io/anon/pen/pJeLdE?editors=110
SimpleJ 2015年

1
@IanSteffy我刚刚在Chrome 45.0.2454.85(64位)上测试了它,并且工作正常……?
Matthemattics 2015年

2
如果它可以在Codepen中工作,但不能在我的项目中工作,那绝对是我的错。我的错。这个答案是正确的!是的,我说!
伊恩S

3
对于不习惯使用多个伪选择器的人们(可能像我到现在为止一样),可能会补充一下为什么会起作用。这里发生的是,这将选择从起始/顶部开始同时是孩子x和从结束开始是孩子y的孩子。因此,只有在确实有x + y个孩子的情况下,才选择某些内容。
莱戈拉斯

7
请注意,:first-child:nth-last-child(1)您也可以使用代替:only-child
亚当·里斯

40

不,不是。有几个选择器可以使您更加接近,但可能无法在您的示例中使用,并且没有最佳的浏览器兼容性。

:only-child

:only-child仅在元素的父代有一个子代的意义上讲,它是为数不多的真正计数选择器之一。使用您理想的示例,它的行为children(1)可能会像这样。

:nth-child

:nth-child这里你要根据你真正希望做的去选择实际上可能得到你。如果要为所有元素设置样式(如果有8个孩子),那么您就不走运了。但是,如果要将样式应用于第8个​​及更高版本的元素,请尝试以下操作:

p:nth-child( n + 8 ){
    /* add styles to make it pretty */
}

不幸的是,这些可能不是您想要的解决方案。最后,您可能需要使用一些Javascript向导来根据数量应用样式-即使您要使用其中一种样式,也需要仔细考虑浏览器的兼容性,然后再使用纯粹的样式。 CSS解决方案。

W3 CSS3伪类规范

编辑我对您的问题的理解有所不同-还有几种其他方式可以设置父级而不是子级。让我按照自己的方式提出其他一些选择器:

:empty:not

这将设置没有子元素的样式。它本身并不是很有用,但是当与:not选择器配对时,您只能设置具有子元素的元素的样式:

div:not(:empty) {
    /* We know it has stuff in it! */
}

您无法在此处计算出多少个纯CSS可用的子级,但是它是另一个有趣的选择器,可让您做一些很酷的事情。


值得注意的是,原始问题已被编辑,使最初的“否”有点误导(只是fyi
Matthemattics

17

注意:此解决方案将返回某些长度的子集,而不是您要求的父元素。希望它仍然有用。

Andre Luis提出了一种方法:http : //lea.verou.me/2011/01/styling-children-based-on-their-number-with-css3/不幸的是,它仅在IE9及更高版本中有效。

本质上,您将:nth-​​child()与其他处理元素位置的伪类组合在一起。这种方法允许您从具有特定长度的元素集中指定元素。

例如 :nth-child(1):nth-last-child(3)匹配集合中的第一个元素,同时也是集合末尾的第三个元素。这有两件事:确保集合仅包含三个元素,并且我们拥有三个元素中的第一个。要指定三个元素集的第二个元素,我们将使用:nth-child(2):nth-last-child(2)


示例1-如果set具有三个元素,则选择所有列表元素:

li:nth-child(1):nth-last-child(3),
li:nth-child(2):nth-last-child(2),
li:nth-child(3):nth-last-child(1) {
    width: 33.3333%;
}

Lea Verou的示例1替代

li:first-child:nth-last-child(3),
li:first-child:nth-last-child(3) ~ li {
    width: 33.3333%;
}


示例2-使用三个列表元素定位set的最后一个元素:

li:nth-child(3):last-child {
    /* I'm the last of three */
}

示例2的替代方法:

li:nth-child(3):nth-last-child(1) {
    /* I'm the last of three */
}


示例3-用集合四个列表元素作为set的第二个元素:

li:nth-child(2):nth-last-child(3) {
    /* I'm the second of four */
}

1
同样,这是同胞的数目,而不是孩子的数目
TMS

@TMS看到接受的答案的编辑-OP的问题措辞尴尬
ifugu

当每个元素需要根据其在列表中的位置进行不同样式设置时,例如,甚至获得圆形变换li:nth-child(3):nth-last-child(1) { transform: rotate(120deg); } li:nth-child(2):nth-last-child(2) { transform: rotate(240deg); },等等,这种方法都是完美的 ……等等
Greg Smith

11

基于Matt的解决方案,我使用了以下Compass / SCSS实现。

@for $i from 1 through 20 {
    li:first-child:nth-last-child( #{$i} ),
    li:first-child:nth-last-child( #{$i} ) ~ li {
      width: calc(100% / #{$i} - 10px);
    }
  }

这使您可以快速扩展项目数。


4
取而代之的是,你可以很容易地使用Flexbox的...
米哈尔Miszczyszyn

6

是的,我们可以像这样使用nth-child来做到这一点

div:nth-child(n + 8) {
    background: red;
}

这将使第8个div子项开始变红。希望这可以帮助...

另外,如果有人说过“嘿,使用CSS样式无法完成操作,请使用JS !!!” 立即怀疑他们。如今,CSS非常灵活

范例:: http://jsfiddle.net/uWrLE/1/

在示例中,前7个孩子是蓝色的,然后8个以上孩子是红色的...


1
也许加上关于不幸的缺乏支持的注释?
benesch 2012年

2
我认为这并不是Brodie的要求-这将按照给定的数量设置元素的样式,但是无法根据其子元素的数量来选择祖先/包含的元素。
Ben Hull

不过,实际上这是一些相当不错的信息,谢谢alan,但是bee是对的,我试图说“如果一个元素有这么多的孩子,我们就是这种风格”。前七个会是孤独而赤裸的。
布罗迪

@primatology-唯一不支持nth-child的浏览器是IE <9。所有其他版本都支持它两个或更多个版本。
罗布

-1这不会使div孩子变成红色,这将使div红色基于其兄弟姐妹中的数字!与div的孩子没有任何关系!
TMS

5

如果要使用纯CSS(使用scss)进行此操作,但在同一父类中具有不同的元素/类,则可以使用此版本!

  &:first-of-type:nth-last-of-type(1) {
    max-width: 100%;
  }

  @for $i from 2 through 10 {
    &:first-of-type:nth-last-of-type(#{$i}),
    &:first-of-type:nth-last-of-type(#{$i}) ~ & {
      max-width: (100% / #{$i});
    }
  }

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.