Universal Electricity
Universal Electricity

Reputation: 775

Why is my nth-child selector selecting the wrong element?

I have this element tree (stolen from Stack Overflow's 404 page):

When we look at it, the highlighted <div> is supposed to be the fourth element. However, doing $('body > div:nth-child(4)') returns the div before. Why is this so? Is is somehow selecting the div in the <noscript> tag? When I remove the <noscript>, it selects properly.

Why is it behaving like that?

Upvotes: 2

Views: 2530

Answers (3)

James Yang
James Yang

Reputation: 1416

see this post

[Step 1]

:nth-child()

Selects all elements that are the nth-child of their parent.

jQuery's implementation of :nth-child(n) is strictly derived from the CSS specification

W3C specification here

The :nth-child(an+b) pseudo-class notation represents an element that has an+b-1 siblings before it in the document tree

So here :nth-child(4) present the full form :nth-child(0n+4), and denote an element has exactly 3 siblings before it in the document tree

noscript tag

see this post

If enabled javascript, The <noscript> tag may not be rendered but can still accessed using nextSibling or prevSibling, so it's counting with nth-child

[Step 2]

body > div is combined with :nth-child just like other pseudo-classes , e.g. a:hover and tr:hover, the :hover is not concern whether it's a a or tr tag, just a special selector

[The Whole Thing]

body>div:nth-child(4) first select body>div, and then select the div which has exactly 3 siblings before it, so the <noscript> tag counting.

Upvotes: 1

Amadan
Amadan

Reputation: 198324

div:nth-child(4) does not give you the 4th div, it gives you the element that is both a div and a 4th child (and gives you nothing if the 4th child is something that is not a div; that is why you are not getting anything for div:nth-child(1)). The 4th div that you want is the 5th child with <noscript> present, and 4th child without it.

From jQuery docs:

The :nth-child(n) pseudo-class is easily confused with :eq(n), even though the two can result in dramatically different matched elements. With :nth-child(n), all children are counted, regardless of what they are, and the specified element is selected only if it matches the selector attached to the pseudo-class. With :eq(n) only the selector attached to the pseudo-class is counted, not limited to children of any other element, and the (n+1)th one (n is 0-based) is selected.

So, if you want the 4th div, you will do body > div:eq(3).

Upvotes: 8

Arqetech
Arqetech

Reputation: 483

Try Changing div:nth-child(4) to div:nth-child(5) I've tested It and It works with 5th child not 4th child. With the 4th child It selects the <div> before the one you want.

Upvotes: -3

Related Questions