Skip to main content
CSS Tip

Dynamic nth-child() using sibling-index() and if()

We can get the index of an element using sibling-index(), and we can express inline conditions using if(). With both features, we can implement :nth-child(An + B).

Instead of:

.container div {
background: blue;
}
.container div:nth-child(An + B) {
background: red;
}

We can do:

@property --g {syntax: "<number>";inherits: false;initial-value: 0;}
.container {
--A: ;
--B: ;
}
.container div {
--n: calc((sibling-index() - var(--B))/var(--A));
--g: calc(sign(var(--n) + .0001) + var(--n) - round(down,var(--n)));

/* when --g is equal to 1, the element is selected by :nth-child(An + B) */
background: if(style(--g: 1): red; else: blue);
}

What's the point, you might ask? It allows us to update the value of A and B on the fly since now they are variables! Something you cannot do using the classic selector.

Overview of nth-child(An + B)

n needs to be a positive integer (zero included).

When the sum is equal to 1, the element matches :nth-child(An + B).

In the demo below, update the :nth-child() selector and the variables --A and --B with the same values to compare the matching.

See the Pen nth-child() using sibling-index() and if() by Temani Afif (@t_afif) on CodePen.

We can also use the function notation and create something easier to use:

@function --nth-child(--A:1, --B:0, --_g <number>: 0) {
--n: calc((sibling-index() - var(--B))/var(--A));
--_g: calc(sign(var(--n) + .0001) + var(--n) - round(down,var(--n)));
result: if(style(--_g: 1): 1;else: 0);
}

.container div {
--g: --nth-child(-2,10);
/* --g is equal to "1" when the element is selected and "0" otherwise */
background: if(style(--g: 1): red; else: blue);
border-radius: calc(var(--g)*50%);
}

⚠️ Limited support (Chrome only for now) ⚠️

See the Pen nth-child() using sibling-index() and if() + function by Temani Afif (@t_afif) on CodePen.


More CSS Tips