Growing with the Web

Detecting number of siblings with CSS

Published
Tags:

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 nth 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);
}

Like this article?
Subscribe for more!