Solution 1 :

nav :last-child includes your single<ul> element. Since there is only one, it is a :last-child. So it applies text-transform: uppercase; to all if its contents, in this case, all three <li> elements. It is also being applied to the last <li>, because it is also a :last-child. To see this more clearly, here is an example with two <ul> elements.

nav :last-child {
   text-transform: uppercase;
}
<nav>
  <ul>
    <li>This is not a last-child, and parent not a last-child</li>
    <li>This is not a last-child, and parent not a last-child</li>
    <li>Last-child of li in this section</li>
  </ul>
  <ul>
    <li>Parent ul of these li's is a last-child</li>
    <li>So all three li's</li>
    <li>Are uppercase</li>
  </ul>
</nav>

nav li:last-child is specific to only li‘s, so it only styles the last <li>.

nav li:last-child {
   text-transform: uppercase;
}
<nav>
  <ul>
    <li>Only applies to li's</li>
    <li>So ul has no style applied</li>
    <li>But this li is a :last-child</li>
  </ul>
  <ul>
    <li>Only applies to li's</li>
    <li>So ul has no style applied</li>
    <li>But this li is a :last-child</li>
  </ul>
</nav>

And finally, nav :not(:last-child) applies to anything that is :not a last-child.

nav :not(:last-child) {
   text-transform: uppercase;
}
<nav>
  <ul>
    <li>This ul is <b>not</b> a :last-child</li>
    <li>So all of its content</li>
    <li>will be uppercase</li>
  </ul>
  <ul>
    <li>This ul <b>is</b> a :last-child</li>
    <li>But these first two li's are not</li>
    <li>So they are uppercase</li>
  </ul>
</nav>

Solution 2 :

nav :not(:last-child) basically it means “everthing after nav but not last child”. Example below:

nav :not(:last-child) {
   text-transform: uppercase;
}
<nav>
  <ul>
    <li>Text1</li>
    <li>Text2</li>
    <li>Text3</li>
    <ul>
      <li>Text4</li>
      <li>This one is :not</li>
    </ul>
  </ul>
</nav>

Solution 3 :

This is because the selector nav :last-child doesn’t select the last child of any particular nav element, it selects any descendent of a nav element which is also the last child among its siblings (the last child of its parent).

So given the elements

<nav>
  <ul>
    <li>Text1</li>
    <li>Text2</li>
    <li>Text3</li>
  </ul>
</nav>

the css:

nav :last-child {
   text-transform: uppercase;
}

will select both the ul and the last li because they are both the last child of their parents.

With the same markup, but with the css

nav :not(:last-child) {
   text-transform: uppercase;
}

the ul will not be selected because it is the last child of its parent. However, the first 2 li elements will be selected because they are not the last child of their parent (among their direct siblings).

Problem :

I have the following html code:

<nav>
  <ul>
    <li>Text1</li>
    <li>Text2</li>
    <li>Text3</li>
  </ul>
</nav>

Using:

nav :last-child {
   text-transform: uppercase;
}

Result is:

  • TEXT1
  • TEXT2
  • TEXT3

Using:

nav li:last-child {
   text-transform: uppercase;
}

Result is:

  • Text1
  • Text2
  • TEXT3

While using:

nav :not(:last-child) {
   text-transform: uppercase;
}

Result is:

  • TEXT1
  • TEXT2
  • Text3

Why “:not(:last-child)” doesn’t need “li” to target the last child?
Thanks.

Comments

Comment posted by Lumi

Better explained than mine 😛

Comment posted by Huangism

for

Comment posted by AbsoluteBeginner

“I can see clearly now, the rain is gone”. Thanks for your answer, Chris!

Comment posted by Lumi

I read it again, and your question is: “Why doesn’t need “li” to target the last child?” and I explained that it takes everything after nav so, same as doing

Comment posted by Calvin Nunes

it’s not

Comment posted by Lumi

The last element inside

By