【问题标题】:Can CSS detect the number of children an element has?CSS 可以检测元素的子元素数量吗?
【发布时间】:2012-02-02 00:05:56
【问题描述】:

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

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

例如

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

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

【问题讨论】:

  • 数量查询SCSS Mixin:codepen.io/jakob-e/pen/wgGpeP
  • @vsync 于 20 年 6 月 3 日编辑的内容应该被还原,因为它以与问题本身或其答案不相符的方式更改了代码示例。
  • @NikRolls - 我的编辑应该不被还原。我只是将问题浓缩为本质——如何根据子节点的数量选择父节点。如果你能做到这一点,那么显然你可以做 OP 想要做的事情,但是 core 是选择器本身,而不是它之后的任何东西。

标签: css css-selectors


【解决方案1】:

澄清:

由于原始问题中的先前措辞,一些 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%;
}

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

这项技术的功劳归于 André Luís(发现)和 Lea Verou(精炼)。

你不只是喜欢 CSS3 吗? ?

CodePen 示例:

来源:

【讨论】:

  • 非常方便。我写了一个利用这种技术的 SASS mixin:codepen.io/anon/pen/pJeLdE?editors=110
  • @IanSteffy 我刚刚在 Chrome 45.0.2454.85(64 位)上进行了测试,它运行良好……?
  • 如果它在 codepen 中有效但不适用于我的项目,那么这绝对是我的错。我的错。这个答案是正确的!没错,我说!
  • 对于那些不习惯使用多个伪选择器的人来说可能会很好地补充一下为什么会这样(就像我直到现在一样;)。这里发生的是,这会选择同时是从开始/顶部的孩子 x 和从结尾的孩子 y 的孩子。所以这只会在恰好有 x+y 个孩子的情况下选择一些东西。
  • 请注意,除了:first-child:nth-last-child(1),您还可以使用:only-child
【解决方案2】:

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

: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 Spec on pseudo-classes

编辑我对您的问题的理解略有不同 - 还有其他几种方法可以设置 父项 的样式,而不是子项。让我按照你的方式扔一些其他选择器:

:empty:not

这会为没有子元素的元素设置样式。单独使用并没有多大用处,但与 :not 选择器搭配使用时,您只能设置具有子元素的元素:

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

你无法计算这里有多少个纯 CSS 可用的子元素,但它是另一个有趣的选择器,可以让你做一些很酷的事情。

【讨论】:

  • 值得注意的是原始问题已被编辑,使最初的“否”有点误导(仅供参考?)
【解决方案3】:

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

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%;
}

示例 1 替代方案来自 Lea Verou:

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


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

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 - 以四个列表元素为目标集合的第二个元素:

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

【讨论】:

  • 再一次,这是兄弟姐妹的数量,而不是孩子
  • @TMS 查看已接受答案的编辑 - OP 的问题措辞很尴尬
  • 这种方法非常适合每个元素需要根据其在列表中的位置进行不同样式设置的情况,例如获得均匀的圆形变换:li:nth-child(3):nth-last-child(1) { transform: rotate(120deg); } li:nth-child(2):nth-last-child(2) { transform: rotate(240deg); } 等等...
【解决方案4】:

根据 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);
    }
  }

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

【讨论】:

  • 除此之外,您可以轻松地使用 Flexbox...
【解决方案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});
    }
  }

【讨论】:

    【解决方案6】:

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

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

    这将使第 8 个div 以后的孩子变为red。希望这会有所帮助...

    另外,如果有人说“嘿,他们不能用 css 来做样式,用 JS!”立即怀疑他们。 CSS 现在非常灵活

    .container div {
      background: blue;
    }
    
    .container div:nth-child(n + 8) {
      background: red;
    }
    <div class="container">
      <div>div 1</div>
      <div>div 2</div>
      <div>div 3</div>
      <div>div 4</div>
      <div>div 5</div>
      <div>div 6</div>
      <div>div 7</div>
      <div>div 8</div>
      <div>div 9</div>
      <div>div 10</div>
      <div>div 11</div>
      <div>div 12</div>
    </div>

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

    [外部示例]

    【讨论】:

    • 也许添加一个关于不幸lack of support的注释?
    • 我不认为这正是 Brodie 所要求的 - 这将在给定数量之后设置 children 的样式,但无法根据它的孩子的数量。
    • 这实际上是一些非常好的信息,谢谢艾伦,但蜜蜂是对的,我想说“如果一个元素有这么多孩子我们这种风格”如果我没记错你的方法给第 8 个孩子穿上造型,但前 7 个孩子会孤独而赤裸。
    • @primatology - 唯一不支持 nth-child 的浏览器是 IE
    • -1 这不会使 div child 变为红色,这将根据 div 在其 兄弟 中的编号使 div 变为红色!与 div 的孩子没有任何关系!
    【解决方案7】:

    不,CSS 中没有这样的东西。但是,您可以使用 JavaScript 计算子元素的数量并应用样式。

    【讨论】:

    • @Lübnah 你能解释为什么它不是真的吗?
    • @GabrielSantos(约翰看着一个红苹果)。 -约翰:我看到了一个蓝色的苹果。 -Max:不是真的,它是红色的。 -John 你能解释一下为什么这不是真的吗?
    【解决方案8】:

    如果您正在寻找一种方法来设置所有元素的样式,如果存在超过 N 个(例如 2 个或更多):

    li:first-child:nth-last-child(n+2),
    li:first-child:nth-last-child(n+2) ~ li {
      background-color: red;
    }
    <ul>
      <li>first</li>
    </ul>
    
    <ul>
      <li>first</li>
      <li>second</li>
    </ul>
    
    <ul>
      <li>first</li>
      <li>second</li>
      <li>third</li>
    </ul>

    【讨论】:

    • 如果它也是倒数第 5 个,是否可以仅用于选择和设置第 6 个元素的样式?如果是这样,那么,例如,当您在移动设备上进行分页显示太多页面时,您可以将一些中心页面设置为 display:none。
    • @F. 当然。这是一个完全不同的要求,但可以使用 li:nth-child(6):nth-last-child(5) { background-color: red } jsfiddle.net/0eahnrfd
    • 由于某种原因不会将显示属性设置为无,但原来的解决方案变得更好
    • 某些原因可能是特异性问题,如果background-color: red 或类似的工作,另一组规则会覆盖它。
    猜你喜欢
    • 2016-09-08
    • 1970-01-01
    • 2022-08-10
    • 2012-10-11
    • 2011-06-01
    • 2014-02-09
    • 1970-01-01
    相关资源
    最近更新 更多