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

前端 未结 8 2033
醉酒成梦
醉酒成梦 2020-12-10 03:37

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

As per W3Schools CSS Selector Reference:

  • p:nth-chil
相关标签:
8条回答
  • 2020-12-10 03:58

    Assume we have following HTML:

    <div id="content">
        <p>a1</p>
        <span>a2</span>
        <p>a3</p>
        <span>a4</span>
    </div>
    

    1) #content p:nth-child(2) -- applies to 0 elements
    because p:nth-child(2) requires it be the second child and that the tag is p, but actually the tag is a <span>.

    2) #content *:nth-child(2) -- apples to <span>a2</span>
    because *:nth-child(2) only requires it be the second child, not require the tag name. * can be any tag name.

    3) #content p:nth-of-type(2) . -- applies to <p>a3</p>
    because p:nth-of-type(2) means the second one in the <p> node list.

    4) #content *:nth-of-type(2) . -- applies to <p>a3</p> and <span>a4</span>
    because *:nth-of-type(2) only requires the second one in the same tag node list.

    0 讨论(0)
  • 2020-12-10 04:02

    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.

    0 讨论(0)
提交回复
热议问题