How to select a range of elements in repeated pattern
Let's say there are 12 items in 4 rows.
| 1 || 2 || 3 |
| 4 || 5 || 6 |
| 7 || 8 || 9 |
| 10 || 11 || 12 |
I want to select and style 2nd row and 4th row, How do I do that?
Note that rows are not in different HTML elements, in fact they are all an ul li element.
Desired Result:
| 1 || 2 || 3 |
|--4---||--5---||--6---|
| 7 || 8 || 9 |
|--10--||--11--||--12--|
I have tried playing with this:
li:nth-child(n+4)
It selects all the elements after first three. Then I tried this:
li:nth-child(n+4):nth-child(-n+8)
This only selects 4, 5 & 6 but I cant repeat this pattern to select 10, 11 & 12 as well. Is there any solution for this in CSS?
Solution 1:
This is a commonly-asked question, but I wanted to point out that the reason :nth-child(n+4):nth-child(-n+6)
only matches one specific range of elements is that it only provides a single start point (n+4) and a single end point (-n+6). The only elements that can be greater than or equal to 4 and less than or equal to 6 are 4, 5 and 6, so it's impossible to match elements outside of this range using the same selector. Adding more :nth-child()
pseudos will only narrow down the matches.
The solution is to think of this in terms of columns, assuming there will always be exactly 3 columns (elements) per row. You have three columns, so you will need three separate :nth-child()
pseudos. Elements 4 and 10 from the first column are 6 elements apart, so the argument to all of the :nth-child()
pseudos needs to start with 6n.
The +b portion in the An+B expression can either be +4, +5 and +6, or 0, -1 and -2 — they will both match the same set of elements:
li:nth-child(6n+4), li:nth-child(6n+5), li:nth-child(6n+6)
li:nth-child(6n), li:nth-child(6n-1), li:nth-child(6n-2)
You cannot do this with a single :nth-child()
pseudo-class, or a single compound selector consisting of any combination of :nth-child()
pseudos, because the An+B notation simply doesn't allow such expressions to be constructed that match elements in ranges as described.
Solution 2:
You can't do this with a single selector and need to use a grouping of nth-child
selectors like in the below snippet:
li:nth-child(6n), li:nth-child(6n-1), li:nth-child(6n-2) {
color: red;
}
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
</ul>
Selector Explanation:
-
li:nth-child(6n)
- Selects the 6th (=6*1), 12th (=6*2), 18th (=6*3) elements and so on. -
li:nth-child(6n-1)
- Selects the 5th (=(6*1)-1), 11th (=(6*2)-1), 17th (=(6*3)-1) elements and so on. -
li:nth-child(6n-2)
- Selects the 4th (=(6*1)-2), 10th (=(6*2)-2), 16th (=(6*3)-2) elements and so on.
Note: Generally n
starts from 0 but I have excluded it in the explanation because we don't have any 0th, -1th or -2nd element.