Difference Between :First-Child and :First-Of-Type

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

A parent element can have one or more child elements:

<div class="parent">
<div>Child</div>
<div>Child</div>
<div>Child</div>
<div>Child</div>
</div>

Among these children, only one of them can be the first. This is matched by :first-child:

<div class="parent">
<div>Child</div> <!-- :first-child -->
<div>Child</div>
<div>Child</div>
<div>Child</div>
</div>

The difference between :first-child and :first-of-type is that :first-of-type will match the first element of its element type, which in HTML is represented by its tag name, even if that element is not the first child of the parent. So far the child elements we're looking at have all been divs, but bear with me, I'll get to that in a bit.

For now, the converse also holds true: any :first-child is also :first-of-type by necessity. Since the first child here is also the first div, it will match both pseudo-classes, as well as the type selector div:

<div class="parent">
<div>Child</div> <!-- div:first-child, div:first-of-type -->
<div>Child</div>
<div>Child</div>
<div>Child</div>
</div>

Now, if you change the type of the first child from div to something else, like h1, it will still be the first child, but it will no longer be the first div obviously; instead, it becomes the first (and only) h1. If there are any other div elements following this first child within the same parent, the first of those div elements will then match div:first-of-type. In the given example, the second child becomes the first div after the first child is changed to an h1:

<div class="parent">
<h1>Child</h1> <!-- h1:first-child, h1:first-of-type -->
<div>Child</div> <!-- div:nth-child(2), div:first-of-type -->
<div>Child</div>
<div>Child</div>
</div>

Note that :first-child is equivalent to :nth-child(1).

This also implies that while any element may only have a single child element matching :first-child at a time, it can and will have as many children matching the :first-of-type pseudo-class as the number of types of children it has. In our example, the selector .parent > :first-of-type (with an implicit * qualifying the :first-of-type pseudo) will match two elements, not just one:

<div class="parent">
<h1>Child</h1> <!-- .parent > :first-of-type -->
<div>Child</div> <!-- .parent > :first-of-type -->
<div>Child</div>
<div>Child</div>
</div>

The same holds true for :last-child and :last-of-type: any :last-child is by necessity also :last-of-type, since absolutely no other element follows it within its parent. Yet, because the last div is also the last child, the h1 cannot be the last child, despite being the last of its type.

:nth-child() and :nth-of-type() function very similarly in principle when used with an arbitrary integer argument (as in the :nth-child(1) example mentioned above), but where they differ is in the potential number of elements matched by :nth-of-type(). This is covered in detail in What is the difference between p:nth-child(2) and p:nth-of-type(2)?

CSS :first-child and :first-of-type (example)

Here's a great explanation on CSS Tricks. Basically, the first child of the #blog div is not an article element; it's a header element. :first-child will match an element if it's the first element in the parent container. :first-of-type will match an element if it's the first element of its type in the parent container regardless of whether or not there are other elements preceding it.

Is there a functional difference between *:first-child and :first-child?

They are identical even if we consider performance. From the specification we can read

If a universal selector represented by * (i.e. without a namespace prefix) is not the only component of a sequence of simple selectors selectors or is immediately followed by a pseudo-element, then the * may be omitted and the universal selector's presence implied.

So writing > :first-child should mean the same as > *:first-child for the browser.

You can also read

Note: it is recommended that the * not be omitted, because it decreases the potential confusion between, for example, div :first-child and div:first-child. Here, div *:first-child is more readable.

So it's not only a matter of preference but it helps avoid confusion and make the code more readable.


In the new sepcification we can also read:

Unless an element is featureless, the presence of a universal selector has no effect on whether the element matches the selector.

and

Note: In some cases, adding a universal selector can make a selector easier to read, even though it has no effect on the matching behavior. For example, div :first-child and div:first-child are somewhat difficult to tell apart at a quick glance, but writing the former as div *:first-child makes the difference obvious.

difference between :first and :first-child not clear

From Official Docs:

The :first pseudo-class is equivalent
to :eq(0). It could also be written as
:lt(1). While this matches only a
single element, :first-child can
match more than one: One for each
parent.

While :first matches only a single element, the :first-child selector can match more than one: one for each parent. This is equivalent to :nth-child(1).

http://api.jquery.com/first-selector/

Update:

Here is an example using :first-child:

http://jsbin.com/olugu

You can view its soruce and edit yourself. If you replace :first-child with :first, it will only highlight the first word there. This is what is defined for them.

And here is example using :first:

http://jsbin.com/olugu/2

Difference between nth-of-type(1) and first-of-type pseudo-classes

From the specification:

Same as :nth-of-type(1). The :first-of-type pseudo-class represents an element that is the first sibling of its type.

They are the same and we all agree with this BUT we may need them for different use cases.

Imagine the case where I need to write a SASS loop to create selector based on indexes. I will be using :nth-of-type

Ex:

@for $i from 1 through $n {
.container > div:nth-of-type(#{$i}) { ... }
}

And sometimes I only need to target the first element so I can simply use first-of-type which will make the code easier to read.

first-child not selecting the first of its type

There is no element that has that class and is the first child. If you want the first element with that class, use .portfolio:first-of-type.

How can I use first of type or fist child to target only the top level one. Not the nested one?

You won't be able to use :first-of-type or :first-child to target only the top level one and ignore the nested one.

Both these pseudo css selectors checks child for immediate parent.
Sample Image

For example, :first-of-type works as:
Sample Image

And :first-child works as:
Sample Image

Difference between div~div and div:not(:first-of-type)?

In terms of matching elements, there is no difference. Any div that follows some other div within the same parent is, by necessity, not the first element of type div within its parent.

If the sibling selector were + and not ~, then div+div has the added condition that the following element must appear immediately after the preceding element. This is not the case with ~ — any number of siblings of any other kind may appear between the two.

If the pseudo-class were :first-child and not :first-of-type, then div:not(:first-child) will still match div:first-of-type if the first div within its parent is not its first child.

Here's an illustration:

<section>
<div></div> <!-- div:first-child or div:first-of-type -->
<div></div> <!-- div+div or div~div or div:nth-of-type(2) -->
<p></p>
<div></div> <!-- div+p+div or div~div or div:nth-of-type(3),
but not div+div -->
</section>
<section>
<h1></h1> <!-- h1:first-child -->
<div></div> <!-- div:first-of-type or div:nth-child(2) -->
<div></div> <!-- div~div or div:nth-of-type(2) or div:nth-child(3) -->
</section>

In terms of specificity, there is a difference. If you have CSS rules with both selectors matching the same elements, then div:not(:first-of-type) will take precedence due to the :first-of-type pseudo-class. Notice that the :not() itself is not counted — only its argument is considered.

Here's another illustration:

div {    float: left;    width: 50px;    height: 50px;    margin: 5px;    border: 1px solid red;}
/* 1 pseudo-class, 1 type -> specificity = 0-1-1 */div:not(:first-of-type) { border-color: green;}
/* 2 types -> specificity = 0-0-2 */div ~ div { border-color: blue;}
<section>    <div></div>    <div></div>    <div></div></section>

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

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.



Related Topics



Leave a reply



Submit