JavaScript JavaScript and the DOM Getting a Handle on the DOM Using CSS Queries to Select Page Elements

Jason Thomas
Jason Thomas
12,518 Points

Why don't indices match parity?

The nth-child(even) returns elements from the collection with odd indices. Why? Lack of consistency just increases cognitive load.

1 Answer

Eric Butler
Eric Butler
31,883 Points

This was an interesting question. After thinking about it, here's my interpretation:

:nth-child and similar pseudo-classes are fed equations, not indexes: :nth-child(an+b). To clarify, :nth-child(even) is just an alias for :nth-child(2n+0); and :nth-child(3) actually evaluates as :nth-child(0n+3). I think it's pretty clear that multiplication is the same in all programming languages, so for example 5n is five times n, and n increments up in a typical programming loop. Here's where I think the misconception is: when you write, for example, :nth-child(5n+1), it seems like the "1" there is selecting the 1st item in that 5-item group, but actually what it's doing is multiplying 5 * n to get the 5th item, then offsetting the selection 1 more to get what is, for that instance of the 5n loop, item 6 -- which is, coincidentally, the 1st instance in the next group. And since n is evaluated to infinity in both directions, it selects the 1st item as the offset when n = 0.

Bottom line: it's the multiplier, not an index, that's 1-based, because that's how math works. There is no index, just a multiplier (that selects the item at the end of each grouping) and an offset (that pushes the selection over into the next grouping).

Here is the official CSS spec, if you want to ponder things further.

Steven Parker
Steven Parker
163,092 Points

I'm not sure the concept of "multipler" is quite correct. You said yourself that ":nth-child(3) actually evaluates as :nth-child(0n+3)1" — so the multiplier there is 0 and the 3 is simply the offset. And that offset value could have been 2 if they had started counting at 0. And "even" could still be 2n+0 with the "0" representing the first item (the 0 index).

Eric Butler
Eric Butler
31,883 Points

Yeah Steven, it's a tough one and I don't know for sure. Personally, it also feels wrong to me to write :nth-child(2n+1) when I want to start with the 1st (index 0) element and repeat by 2s.

Still, I don't think it's simply that CSS just arbitrarily decided to use 1-based indexing, that feels like a dismissive viewpoint (akin to people saying "CSS isn't a real language"). I feel like the answer lies somewhere in the idea that it's a mathematical formula and the "1" or "+1" in "(2n+1)" is not an index, which is I think what programmers expect and where the confusion starts. Beyond that, though, I'm not smart enough to give a good answer.

Anyway, thanks for writing! It's not everyday I get to interact with the highest-scoring Treehouse user of all time!! Cheers man.

Steven Parker
Steven Parker
163,092 Points

Aww, you made me blush. :blush: Happy coding!

Jason Thomas
Jason Thomas
12,518 Points

I searched around and was unable to find a compelling rationale, but I do agree with Eric that

I don't think it's simply that CSS just arbitrarily decided to use 1-based indexing, that feels like a dismissive viewpoint

There isn't a clear answer to what I asked, but I want to award 'best answer' anyhow. I wish I could give 1/2 best answer to you both. Since I can't do that I decided to award Eric because he pointed at the CSS spec... I need to start going straight to documentation more often! Also, Steven probably doesn't need the points quite as badly :P

Thank you both for participating in the discussion!