Styles Based on Number of Children

Can CSS detect the number of children an element has?

Clarification:

Because of a previous phrasing in the original question, a few SO citizens have raised concerns that this answer could be misleading. Note that, in CSS3, styles cannot be applied to a parent node based on the number of children it has. However, styles can be applied to the children nodes based on the number of siblings they have.


Original answer:

Incredibly, this is now possible purely in 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%;
}

The trick is to select the first child when it's also the nth-from-the-last child. This effectively selects based on the number of siblings.

Credit for this technique goes to André Luís (discovered) & Lea Verou (refined).

Don't you just love CSS3? /p>

CodePen Example:

  • https://codepen.io/mattlubner-the-decoder/pen/ExaQZQR

Sources:

  • http://andr3.net/blog/post/142 (André Luís)
  • http://lea.verou.me/2011/01/styling-children-based-on-their-number-with-css3/ (Lea Verou)

Can I detect the number of children,While the Children Count will exceed four, in CSS?

You don't have to use Javascript to accomplish this. Heydon Pickering wrote a great article about using various pseudo selectors to style content based on count. I highly recommend reading the article.

nth-last-child(n+4) on its own gets you every element that is 4+ from the end. With 5 elements only the first is select, 6 elements 1 and 2 are selected, etc.

nth-last-child(n+4) ~ li is what makes the entire thing come together. ~ is the sibling selector. Used in this scenario anything before ~ is selected as well as anything that is a direct sibling to the previous matches and matches li.

Update

Based on your comment in the original question I've added an additional CSS selector to get 3 or fewer. If you want only 3 change -n+3 to 3.

Unless you're proposed with a challenge, or really like thinking about nth children, this isn't something you'd normally pick up making Javascript seem like your only solution.

li:nth-last-child(-n+3):first-child,
li:nth-last-child(-n+3):first-child ~ li {
/* 3 or Less */
color: blue;
}

li:nth-last-child(n+4),
li:nth-last-child(n+4) ~ li {
/* 4 or More */
color: red;
}
<ul>
<li>1</li>
<li>2</li>
</ul>

<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
</ul>

Styles based on number of children

Try the following:

.widget {
@for $j from 2 through 5 {
@for $i from 1 through $j {
&:nth-of-type(#{$j + 1 - $i}):nth-last-of-type(#{$i}),
&:nth-of-type(#{$j + 1 - $i}):nth-last-of-type(#{$i}) ~ .widget {
width: (1000px / $j);
}
}
}
}

(see the edited pen).

The general rule — for each count of widgets, the sum of numbers in nth-* and nth-last-* must be the number of widgets plus 1, and the overall width must be divided by the number of widgets.

Applying styles only when parent contains X amount of children?

By combining :nth-child(), :nth-last-child() and the ~ combinator you can accomplish this.

You need two selectors. The first one will select the first image, only if it's also the last child of whatever number is specified in the argument of :nth-last-child(). To select the rest of the images that follow, you add on ~ to the selector (which targets all images that follow the first image that satisfy the above condition).

So if I wanted to target images when there is 3 per row, I would use:

div img:nth-child(1):nth-last-child(3),
div img:nth-child(1):nth-last-child(3) ~ img {
border-radius: 50%;
}

Fiddle: http://jsfiddle.net/vp1Ljm3o/

Can I style an element depending on the number of children

There is currently no way to select a parent via it's children using CSS.

Select last 3 children based on the number of children

Is this what you are looking for?

.flex-item:first-child:nth-last-child(7)

targets the first child when there are only 7 items so that

.flex-item:first-child:nth-last-child(7)~.flex-item:nth-child(n+5)

is only triggered when there are 7 items

.flex-container {  display: flex;  flex-flow: row wrap;  justify-content: space-between;  padding: 0;  margin: 0;  list-style: none;}
.flex-item { background: tomato; padding: 5px; width: 200px; height: 150px; margin-top: 10px; line-height: 150px; color: white; font-weight: bold; font-size: 3em; text-align: center;}
.flex-item:first-child:nth-last-child(7),.flex-item:first-child:nth-last-child(7)~.flex-item:nth-child(-n+4) { flex-basis: 23%;}
.flex-item:first-child:nth-last-child(7)~.flex-item:nth-child(n+5) { flex-basis: 31%; background: blue;}
<ul class="flex-container">  <li class="flex-item first">1</li>  <li class="flex-item">2</li>  <li class="flex-item">3</li>  <li class="flex-item">4</li>  <li class="flex-item">5</li>  <li class="flex-item">6</li>  <li class="flex-item">7</li></ul><br/><br/><ul class="flex-container">  <li class="flex-item first">1</li>  <li class="flex-item">2</li>  <li class="flex-item">3</li>  <li class="flex-item">4</li>  <li class="flex-item">5</li>  <li class="flex-item">6</li>  <li class="flex-item">7</li>  <li class="flex-item">8</li>  <li class="flex-item">9</li>  <li class="flex-item">10</li></ul><br/><br/><ul class="flex-container">  <li class="flex-item first">1</li>  <li class="flex-item">2</li>  <li class="flex-item">3</li>  <li class="flex-item">4</li>  <li class="flex-item">5</li></ul>

How to add style to second-to-last only if total number of children are even?

You can use a combination of two selectors like in the below snippet.

When the parent has an even number of children elements, the second last element must be an odd numbered one and so if an element matches both nth-last-child(2) and nth-child(odd) then it means that it is the second last child of the parent and the parent has an even number of elements.

li:nth-last-child(2):nth-child(odd) {  color: red;}
<ul>  <li>One</li>  <li>Two</li>  <li>Three</li>  <li>Four</li></ul>
<ul> <li>One</li> <li>Two</li> <li>Three</li></ul>

Apply CSS styles to an element depending on its child elements

The syntax for that is:

div:has(div.a) { border: solid 3px red; }
div:has(div.b) { border: solid 3px blue; }

As far as I'm aware, styling a parent element based on the child element is not an available feature of CSS. You'll likely need scripting for this.

It'd be wonderful if you could do something like div[div.a] or div:containing[div.a] as you said, but this isn't possible.

You may want to consider looking at jQuery. Its selectors work very well with 'containing' types. You can select the div, based on its child contents and then apply a CSS class to the parent all in one line.

If you use jQuery, something along the lines of this would may work (untested but the theory is there):

$('div:has(div.a)').css('border', '1px solid red');

or

$('div:has(div.a)').addClass('redBorder');

combined with a CSS class:

.redBorder
{
border: 1px solid red;
}

Here's the documentation for the jQuery "has" selector.



Related Topics



Leave a reply



Submit