Skip to main content
CSS Tip

Range Selection using Modern CSS

Similar to the dynamic :nth-child(), we can use if() and math functions to emulate a range selection.

Instead of:

/* select any element in the range [X Y] */
.container div:nth-child(n + X):nth-child(-n + Y) {
background: red;
}

We can do:

@property --g {syntax: "<integer>";inherits: true;initial-value: 0;}
.container {
--X: ;
--Y: ;
}
.container div {
--g: sign((sibling-index() - var(--X) + 1)*(var(--Y) - sibling-index() + 1));
/* when --g is equal to 1, the element is selected by :nth-child(n + X):nth-child(-n + Y) */
background: if(style(--g: 1): red;);
}

Why reinvent the wheel? With this method, you can update the values of X and Y on the fly, since they are now variables! Something you cannot do using a classic selector.

Overview of :nth-child(n + X):nth-child(-n + Y)

n needs to be a positive integer (zero included), so (index - X)*(Y - index) needs to be positive as well. The sign() function returns 1 when the result is positive and -1 otherwise. We need to add + 1 to the formula to include zero: (index - X + 1)*(Y - index + 1).

In the demo below, update the :nth-child() selector and the variables --X and --Y with the same values to compare the selection.

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

See the Pen Range selection using modern CSS by Temani Afif (@t_afif) on CodePen.

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

@function --range(--X:1, --Y:1, --_g <integer>: 0) {
--_g: sign((sibling-index() - var(--X) + 1)*(var(--Y) - sibling-index() + 1));
result: var(--_g);
}

.container div {
--g: --range(3,8);
background: if(style(--g: 1): red;);
}

See the Pen Range selection using modern CSS by Temani Afif (@t_afif) on CodePen.


More CSS Tips