Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between p:nth-child(2) and p:nth-of-type(2)?

What is the difference between p:nth-child(2) and p:nth-of-type(2)?

As per W3Schools CSS Selector Reference:

  • p:nth-child(2): Selects every <p> element that is the second child of its parent.
  • p:nth-of-type(2): Selects every <p> element that is the second <p> element of its parent.

The difference seem to be child of its parent and <p> element of its parent.

If we are already mentioning the element type as <p> in both the cases and the keyword parent establishes a parent-child relation, so what can be the difference?

like image 295
undetected Selenium Avatar asked Sep 25 '18 07:09

undetected Selenium


People also ask

What is difference between nth child and nth-of-type?

As a general rule, if you want to select an interval of a selector regardless of the type of element it is, use nth-child . However, if you want to select a specific type only and apply an interval selection from there, use nth-of-type .

What is the difference between first child and first of type?

The :first-child: The :first-child selector is used to select those elements which are the first-child elements. For :first-child selector the <! DOCTYPE> must be declared for IE8 and earlier versions. The :first-of-type: The :first-of-type Selector is used to targeting the first child of every element of it's parent.

What is nth type?

The :nth-of-type() pseudo-class represents an element that has an+b siblings with the same expanded element name before it in the document tree, for any zero or positive integer value of n, and has a parent element.

Can you use nth-of-type with a class?

There cannot be a way to select :nth-of-type() of a class, because :nth-of-type() only selects the nth child of its type.


4 Answers

For p:nth-child(2) it selects the second element of its parent element if it's a paragraph whereas p:nth-of-type(2) will select the second paragraph of its parent element. If you are still confused let's make me clarify it for you. Consider the code snippet below:

<section>
   <h1>Words</h1>
   <p>Little</p>
   <p>Piggy</p>    <!-- Want this one -->
</section>

Here, p:nth-child(2) will select <p>Little</p> because it is the second child of its parent and it a paragraph element.

But, Here, p:nth-of-type(2) will select <p>Piggy</p> because it will select the second paragraph among all the paragraph of its parent.

Help from: https://css-tricks.com/the-difference-between-nth-child-and-nth-of-type/

like image 89
optimistic_creeper Avatar answered Nov 06 '22 01:11

optimistic_creeper


This question may remind you of What is the difference between :first-child and :first-of-type? — and in fact, a lot of parallels can be drawn between the two. Where this question greatly differs from the other is the arbitrary integer argument X, as in :nth-child(X) and :nth-of-type(X). They're similar in principle to their "first" and "last" counterparts, but the potentially matching elements vary greatly based on what's actually in the page.

But first, some theory. Remember that simple selectors are independent conditions. They remain independent even when combined into compound selectors. That means that the p neither is influenced by, nor influences, how :nth-child() or :nth-of-type() matches. Combining them this way simply means that elements must match all of their conditions simultaneously in order to match.

Here's where things get interesting. This independent matching means I can get pretty creative in how I express compound (and complex) selectors in terms of plain English, without changing the meaning of the selectors. In fact, I can do so right now in a way that makes the difference between :nth-child(2) and :nth-of-type(2) seem so significant that the pseudo-classes might as well be completely unrelated to each other (except for the "siblings" part anyway):

  • p:nth-child(2): Select the second child among its siblings if and only if it is a p element.

  • p:nth-of-type(2): Select the second p element among its siblings.

All of a sudden, they sound really different! And this is where a bit of explanation helps.

Any element may only have a single child element matching :nth-child(X) for any integer X at a time. This is why I've chosen to emphasize "the second child" by mentioning it first. In addition, this child element will only match p:nth-child(X) if it happens to be of type p (remember that "type" refers to the tagname). This is very much in line with :first-child and :last-child (and, similarly, p:first-child and p:last-child).

There's two aspects to :nth-of-type(X) on the other hand:

  1. Because the "type" in :nth-of-type() is the same concept as the "type" in a type selector, this family of pseudo-classes is designed to be used in conjunction with type selectors (even though they still operate independently). This is why p:nth-of-type(2) can be expressed as succinctly as "Select the second p element among its siblings." It just works!

  2. However, unlike :first-of-type and :last-of-type, the X requires that there actually be that many child elements of the same type within their parent element. For example, if there's only one p element within its parent, p:nth-of-type(2) will match nothing within that parent, even though that p element is guaranteed to match p:first-of-type and p:last-of-type (as well as, by extension, p:only-of-type).

An illustration:

<div class="parent">
  <p>Paragraph</p>
  <p>Paragraph</p>          <!-- [1] p:nth-child(2), p:nth-of-type(2) -->
  <p>Paragraph</p>
  <footer>Footer</footer>
</div>

<div class="parent">
  <header>Header</header>
  <p>Paragraph</p>          <!-- [2] p:nth-child(2) -->
  <p>Paragraph</p>          <!-- [3] p:nth-of-type(2) -->
  <footer>Footer</footer>
</div>

<div class="parent">
  <header>Header</header>
  <figure>Figure 1</figure>
  <p>Paragraph</p>          <!-- [4] -->
  <footer>Footer</footer>
</div>

<div class="parent">
  <header>Header</header>
  <p>Paragraph</p>          <!-- [2] p:nth-child(2) -->
  <figure>Figure 1</figure>
  <hr>
  <figure>Figure 2</figure> <!-- [5] .parent > :nth-of-type(2) -->
  <p>Paragraph</p>          <!-- [5] .parent > :nth-of-type(2) -->
  <p>Paragraph</p>
  <footer>Footer</footer>
</div>

What's selected, what's not, and why?

  1. Selected by both p:nth-child(2) and p:nth-of-type(2)
    The first two children of this element are both p elements, allowing this element to match both pseudo-classes simultaneously for the same integer argument X, because all of these independent conditions are true:

    • it is the second child of its parent;
    • it is a p element; and
    • it is the second p element within its parent.
  2. Selected by p:nth-child(2) only
    This second child is a p element, so it does match p:nth-child(2).

    But it's the first p element (the first child is a header), so it does not match p:nth-of-type(2).

  3. Selected by p:nth-of-type(2) only
    This p element is the second p element after the one above, but it's the third child, allowing it to match p:nth-of-type(2) but not p:nth-child(2). Remember, again, that a parent element can only have one child element matching :nth-child(X) for a specific X at a time — the previous p is already taking up the :nth-child(2) slot in the context of this particular parent element.

  4. Not selected
    This p element is the only one in its parent, and it's not its second child. Therefore it matches neither :nth-child(2) nor :nth-of-type(2) (not even when not qualified by a type selector; see below).

  5. Selected by .parent > :nth-of-type(2)
    This element is the second of its type within its parent. Like :first-of-type and :last-of-type, leaving out the type selector allows the pseudo-class to potentially match more than one element within the same parent. Unlike them, how many it actually matches depends on how many of each element type there actually are.

    Here, there are two figure elements and three p elements, allowing :nth-of-type(2) to match a figure and a p. But there's only one header, one hr, and one footer, so it won't match elements of any of those types.

In conclusion, :nth-child() and :nth-of-type(), with an integer argument X (i.e. not in the form An+B with a coefficient A of n), function pretty similarly to :first-child/:last-child and :first-of-type/:last-of-type, with the major difference being that the argument, along with the page itself, influences how many different elements may be matched with :nth-of-type().

Of course, there's a whole lot more to :nth-child() and :nth-of-type() than just a simple integer argument, but needless to say the details and possibilities thereof are outside the scope of this question.

like image 10
BoltClock Avatar answered Nov 06 '22 03:11

BoltClock


  • p:nth-child(1): Means that is the first child of any parent and is of type paragraph.
  • p:nth-of-type (1): Means that is the first appearance of the type paragraph within any parent

p:nth-child(2){background:#f00;}
p:nth-of-type(2){background:#0f0;}
<div>
   <div>first child</div>
   <p>second child and first element of class "p"</p>
   <p>third child and second element of class "p"</p>
   <p>fourth child and third element of class "p"</p>
</div>
like image 9
saloni bhut Avatar answered Nov 06 '22 03:11

saloni bhut


The other answers hightlighted the main difference between both selectors which is the fact that nth-child will consider all the elements inside the same container (siblings elements) and nth-of-type will consider all the elements with the same type inside the same container.

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

The :nth-of-type(an+b) pseudo-class notation represents an element that has an+b-1 siblings with the same expanded element name before it in the document treeref

From this we can add another important difference between both selectors which is the fact that nth-of-type is generally used with a tag selector whereas nth-child doesn't need a tag selector. In other words, nth-of-type can select more than one element but nth-child can select only one element. Adding a tag selector with nth-of-type will restrict the selection to one element and adding a tag selector to nth-child will simply add more restriction to the one element we are targeting.1


nth-child()

This selector will select the 2nd child of .container.

.container :nth-child(2) {
  border:1px solid red;
}
<div class="container">
  <p>aaa</p>
  <p>aaa</p>
  <h1>title</h1>
  <p>aaa</p>
  <p>aaa</p>
  <p>aaa</p>
  <h1>title</h1>
</div>

This is the same selector as above but we add a tag restriction: Find the 2nd child of .container, if it's a p tag then select it.

.container p:nth-child(2) {
  border:1px solid red;
}
<div class="container">
  <p>aaa</p>
  <p>aaa</p>
  <h1>title</h1>
  <p>aaa</p>
  <p>aaa</p>
  <p>aaa</p>
  <h1>title</h1>
</div>

If we change p with h1 nothing will be selected because the 2nd child isn't a h1:

.container h1:nth-child(2) {
  border:1px solid red;
}
<div class="container">
  <p>aaa</p>
  <p>aaa</p>
  <h1>title</h1>
  <p>aaa</p>
  <p>aaa</p>
  <p>aaa</p>
  <h1>title</h1>
</div>

nth-of-type()

This selector will select the 2nd p and the 2nd h1. nth-of-type will behave like nth-child after grouping elements by the same type.

.container :nth-of-type(2) {
  border:1px solid red;
}
<div class="container">
  <p>aaa</p>
  <p>aaa</p>
  <h1>title</h1>
  <p>aaa</p>
  <p>aaa</p>
  <p>aaa</p>
  <h1>title</h1>
</div>

So we select the 2nd child inside this:

<div class="container">
  <p>aaa</p>
  <p>aaa</p> <-- this one -->
  <p>aaa</p>
  <p>aaa</p>
  <p>aaa</p>
</div>

Then the 2nd child inside this:

<div class="container">
  <h1>title</h1>
  <h1>title</h1> <-- this one -->
</div>

Adding a tag selector will simply restrict the selection to only one group of element:

.container p:nth-of-type(2) {
  border:1px solid red;
}
.container h1:nth-of-type(2) {
  border:1px solid green;
}
<div class="container">
  <p>aaa</p>
  <p>aaa</p>
  <h1>title</h1>
  <p>aaa</p>
  <p>aaa</p>
  <p>aaa</p>
  <h1>title</h1>
</div>

If your container contains only one type of element both selectors will for sure give the same result but will not behave the same (i.e. the alogirthm behind will be different). You may also notice that if you remove the tag selector from both you will also have the same result:

.container :nth-of-type(2) {
  border:1px solid red;
}
.container :nth-child(2) {
  color:red;
}

/* The below will also select the same
  .container p:nth-child(2)
  .container p:nth-of-type(2)
  .container *:nth-child(2)
  .container *:nth-of-type(2)
*/
<div class="container">
  <p>aaa</p>
  <p>aaa</p>
  <p>aaa</p>
  <p>aaa</p>
  <p>aaa</p>
</div>

Another difference (this is a personal thought) may be the performance of both. nth-child can be faster since it consider all the siblings elements at once so it's like we will have one loop to check all the elements. nth-of-type need to consider different type of elements not at the same time so we will probably have more processing thus it's slower (This is my own conclusion based on how both works. I have no formal proof of it).


1: I am considering a selection inside one container using an integer within nth-child/nth-of-type.

like image 6
Temani Afif Avatar answered Nov 06 '22 03:11

Temani Afif