cd Structural Pseudo-classes | Dev Notes | Nikita Goluban

⬅ Back

STRUCTURAL PSEUDO-CLASSES

Precision is a sign of mastery.

Sometimes we do not want to style all elements.

We may want to style only:

Structural pseudo-classes help solve exactly these problems.

1. Neighboring Elements and Siblings

Structural pseudo-classes let us select specific elements from a group of child elements without adding extra classes.

Child elements in the same group are also called siblings.

Siblings are elements that have the same parent.

Example

<ul class="list">
  <li class="list-item">
    <a class="list-link">Link 1</a>
  </li>
  <li class="list-item">
    <a class="list-link">Link 2</a>
  </li>
  <li class="list-item">
    <a class="list-link">Link 3</a>
  </li>
</ul>

In this example:

The a.list-link elements are not selected as one sibling group here for this purpose, because each link is inside its own li.

So in practice, structural pseudo-classes are usually applied to the li elements here.

Diagram

ul
├── li.list-item
│   └── a.list-link
├── li.list-item
│   └── a.list-link
└── li.list-item
    └── a.list-link

The li elements are siblings.

That is why they can be targeted with structural pseudo-classes.

2. :first-child and :last-child

The pseudo-classes :first-child and :last-child let us style only:

Example

<ul class="list">
  <li class="list-item">HTML</li>
  <li class="list-item">CSS</li>
  <li class="list-item">JavaScript</li>
  <li class="list-item">React</li>
</ul>
.list-item {
  color: blue;
}

.list-item:first-child {
  color: red;
}

.list-item:last-child {
  color: green;
}

What Happens

Diagram

1. HTML        -> red
2. CSS         -> blue
3. JavaScript  -> blue
4. React       -> green

3. Real Use Case: Removing Extra Margin

A very common layout problem is spacing between list items.

Example

.list-item {
  margin-bottom: 12px;
}

Problem

Solution with :last-child

.list-item {
  margin-bottom: 12px;
}

.list-item:last-child {
  margin-bottom: 0;
}

Why This Matters

Outer spacing at the edges of a group should usually be removed.

Otherwise it may:

Diagram

Without cleanup:

Item 1
margin

Item 2
margin

Item 3
margin  <- unnecessary extra space

With :last-child:

Item 1
margin

Item 2
margin

Item 3
(no extra margin below)

4. :not() Pseudo-class

The :not() pseudo-class selects all elements that do not match a given condition.

Syntax

:not(selector)

The selector inside :not() should be a simple selector, for example:

Main Idea

:not() means "select everything except this."

5. Using :not() for Margins

Instead of:

we can write one cleaner rule:

.list-item:not(:last-child) {
  margin-bottom: 20px;
}

How to Read It

Apply styles to all .list-item elements that are not the last child.

So this selector styles:

Why This Is Often Better

Diagram

.list-item:not(:last-child)

✓ first item
✓ middle items
✗ last item

Extra Example

.button:not(.active) {
  opacity: 0.6;
}

Meaning

style all buttons except the active one.

6. :nth-child()

The pseudo-class :nth-child(an + b) selects elements by number inside a sibling group.

It uses a formula or pattern.

Syntax

:nth-child(an + b)

Where

Main Idea

:nth-child() lets us select elements by position.

7. Example Formula: 2n + 1

If:

then the formula is:

2n + 1

This selects all odd-numbered elements.

Calculation

n = 0 -> 2*0 + 1 = 1
n = 1 -> 2*1 + 1 = 3
n = 2 -> 2*2 + 1 = 5
n = 3 -> 2*3 + 1 = 7
...

So it selects:

8. Practical Use of :nth-child()

In practice, :nth-child() is often used for:

Example List

<ul class="list">
  <li class="list-item">1</li>
  <li class="list-item">2</li>
  <li class="list-item">3</li>
  <li class="list-item">4</li>
  <li class="list-item">5</li>
  <li class="list-item">6</li>
  <li class="list-item">7</li>
  <li class="list-item">8</li>
  <li class="list-item">9</li>
  <li class="list-item">10</li>
</ul>

9. Selecting Even Elements

To select all even elements:

.list-item:nth-child(2n) {
  background-color: orange;
}

or:

.list-item:nth-child(even) {
  background-color: orange;
}

These two forms mean the same thing.

Selected Items

2, 4, 6, 8, 10

Diagram

1  -> normal
2  -> orange
3  -> normal
4  -> orange
5  -> normal
6  -> orange
7  -> normal
8  -> orange
9  -> normal
10 -> orange

10. Selecting Odd Elements

To select all odd elements:

.list-item:nth-child(2n + 1) {
  background-color: orange;
}

or:

.list-item:nth-child(odd) {
  background-color: orange;
}

These two forms also mean the same thing.

Selected Items

1, 3, 5, 7, 9

Diagram

1  -> orange
2  -> normal
3  -> orange
4  -> normal
5  -> orange
6  -> normal
7  -> orange
8  -> normal
9  -> orange
10 -> normal

11. Quick Comparison

:first-child

Selects the first sibling element.

Example:

.list-item:first-child {
  color: red;
}

:last-child

Selects the last sibling element.

Example:

.list-item:last-child {
  margin-bottom: 0;
}

:not()

Selects everything except what is inside the parentheses.

Example:

.list-item:not(:last-child) {
  margin-bottom: 20px;
}

:nth-child()

Selects elements by position or pattern.

Example:

.list-item:nth-child(even) {
  background-color: orange;
}

12. Very Short Practical Examples

First Item

.list-item:first-child {
  font-weight: bold;
}

Meaning

make only the first item bold.

Last Item

.list-item:last-child {
  border-bottom: none;
}

Meaning

remove the bottom border from the last item.

All Except the Last

.list-item:not(:last-child) {
  margin-bottom: 16px;
}

Meaning

add spacing between items, but not after the last one.

All Even Items

.list-item:nth-child(even) {
  background: #f0f0f0;
}

Meaning

every second item gets a different background.

All Odd Items

.list-item:nth-child(odd) {
  background: #ddd;
}

Meaning

the 1st, 3rd, 5th, and so on get a different background.

13. Full Simple Example

HTML

<ul class="list">
  <li class="list-item">HTML</li>
  <li class="list-item">CSS</li>
  <li class="list-item">JavaScript</li>
  <li class="list-item">React</li>
</ul>

CSS

.list-item {
  padding: 8px;
}

.list-item:first-child {
  color: red;
}

.list-item:last-child {
  color: green;
}

.list-item:not(:last-child) {
  margin-bottom: 10px;
}

.list-item:nth-child(even) {
  background-color: #f2f2f2;
}

What Happens Here

14. Common Mistakes

Mistake 1

Using structural pseudo-classes on elements that are not siblings in the same group.

Mistake 2

Forgetting that :first-child and :last-child depend on position inside the parent.

Mistake 3

Using margin-bottom on all items and forgetting to remove it from the last one.

Mistake 4

Confusing odd and even.

Remember:

Mistake 5

Thinking :not() only works with classes.

It can also be used with pseudo-classes and other simple selectors.

15. Short Cheat Sheet

:first-child  -> first element
:last-child   -> last element
:not(...)     -> everything except ...
:nth-child()  -> element by number or pattern

16. Final Summary

Structural pseudo-classes help us style elements based on their position among siblings.

They are useful when we need precision without adding extra classes.

The most common ones are:

They are especially useful for:

Super Short Memory Line

first-child = first, last-child = last, not() = except, nth-child() = by number
⬅ Back