Detecting number of siblings with CSS
I came across a clever CSS technique, originally developed by André Luís in 2009 and later refined by Lea Verou 2 years later; applying a style when the number of siblings is a particular number. It’s definitely worth knowing.
This has a bunch of potential applications, a particularly nice one is styling a series of siblings to fill the width of the container (provided flexbox isn’t suitable).
Here is an example that lays out li
elements using float:left
.
li {
float: left;
}
/* one item */
li:first-child:nth-last-child(1) {
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%;
}
It works by selecting the first child, then the n
th last child which will only exist if there is at least n
siblings. The order in which the rules are defined ensures that the correct rule(s) are applied to the siblings.
See the Pen Detect number of siblings with CSS by Daniel Imms (@Tyriar) on CodePen
This technique can be applied in Sass by using a mixin.
@mixin space-out($min, $max) {
@for $i from $min through $max {
&:first-child:nth-last-child(#{$i}),
&:first-child:nth-last-child(#{$i}) ~ & {
width: 1 / $i * 100%;
}
}
}
li {
@include space-out(1, 4);
}
LESS is a little trickier as looping isn’t as intuitive but it’s doable as well.
.space-out(@min, @max) {
.space-out-loop(@i) when (@i > 0) {
.space-out-loop(@i - 1);
&:first-child:nth-last-child(@{i}),
&:first-child:nth-last-child(@{i}) ~ & {
width: 1 / @i * 100%;
}
}
.space-out-loop(@max);
}
li {
.space-out(1, 4);
}