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.
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
- CSS Shapes using corner-shape Recreate all the common CSS shapes using corner-shape and border-radius.
- Why :is(::before,::after) doesn't work? Learn why the :is() selector doesn't work with pseudo-elements.