:nth-child() counts line breaks as spans in CSS
I was diddling around and working with this markup:
<h1>
Hidd<span>e</span>n
<br>
Br<span>a</span>in
</h1>
I wanted to select the second <span>
so, naturally:
.span:nth-child(2) { ... }
And gosh darn it was I surprised that my styles weren’t showing up! Making sure I had the syntax right, I went for:
.span:nth-child(1) { ... }
It worked! More head scratching. Hmm, OK, why not?
.span:nth-child(3) { ... }
By golly, not only did that work but it selected the second <span>
in the process, giving me exactly what I had aimed for. CSS apparently selects <br>
elements when counting :nth-child()
. New to me!
And guess what? It worked when I put any dang element in place <br>
. Everything, like <div>
, <main>
, <input>
, <abbr>
, <kbd>
, you name it.
I can’t find anything in the Selectors Level 4 spec on the :nth-child()
side of things. I also looked at the HTML Standard and came up empty on the <span>
side of things. I even thought that perhaps it was just a bug with Safari, but it works across the board.
I dunno. Maybe I’m overlooking something obvious. But today I learned that :nth-child()
counts all elements when it searches spans. I mean, look, it counts the only <span>
inside an element when it’s the last child, like:
<!-- Not that you'd ever do this -->
<h1>
Hidd<div>e</div>n
<abbr></abbr>
Br<span>a</span>in
</h1>
10 Comments
“CSS apparently selects
<br>
elements when counting :nth-child()”That’s not the case here.
span:nth-child(2)
will select an element that’s bothspan
and:nth-child(2)
. Since<br>
is the 2nd child your selector didn’t match any element, making you move to:nth-child(3)
.I also incorrectly interpreted this behavior before, while exploring an
:nth-of-class
selector.The proper selector you’re looking for is
:nth-child(2 of span)
, but that’s only supported by Safari at the moment.Well hot dang, thanks Bramus! That’s exactly what I want to know. ????????????
I think this is exactly what happens. A
span:nth-child(3)
selector will match only thespan
that is also its parent’s 3rd child. Yourbr
isn’t counted as a span, it’s counted as a child element.I think :nth-child can be a tricky one to understand. When you write
span:nth-child(3)
, what you’re saying is, “give me allspan
elements that are the 3rd child of their parents.” So it doesn’t really matter what the siblings of the span are. The same goes for any other element/selector. The CSS level 4 spec lets you do what you’re shooting for here with the “of S” part of the selector (see https://drafts.csswg.org/selectors/#example-3c07f717), but I don’t know if it’s supported anywhere yet. In the meantime, as long as you’re only selecting on a tag name, you could build a selector with:nth-of-type
. To get the 2ndspan
that is a child ofh1
, you would do this:h1 > span:nth-of-type(2)
. In case this doesn’t make sense, I put together a codepen: https://codepen.io/kswedberg/pen/XWavPNBHeck yeah, thanks Karl! You and Bramus nailed it. The distinction between “this is a span that is the third child” and “this is the third span child” is exactly what I was mixing up.
Comments are closed.
Likes