Question
I have multiple elements with the class red, and I want to style only the first one inside .home. I tried this CSS:
.home .red:first-child {
border: 1px solid red;
}
With this HTML:
<div class="home">
<span>blah</span>
<p class="red">first</p>
<p class="red">second</p>
<p class="red">third</p>
<p class="red">fourth</p>
</div>
Why does this selector not match the first .red element, and how can I correctly target the first relevant element with the class red?
Short Answer
By the end of this page, you will understand how CSS pseudo-classes like :first-child actually work, why .red:first-child does not match the first .red in this HTML, and which selectors to use instead depending on your document structure.
Concept
CSS selectors do not read like plain English. A selector such as .red:first-child does not mean “the first element with class red.” It means:
- select an element with class
red - only if that same element is also the first child of its parent
In the example HTML, the first child inside .home is this element:
<span>blah</span>
That means the first <p class="red"> is not the first child of .home, because a <span> comes before it. So the selector does not match anything.
This matters because CSS structural pseudo-classes such as :first-child, :last-child, and :nth-child() depend on the element's position among all siblings, not just among elements with a specific class.
If you want “the first p.red” or “the first paragraph of its type,” you need a selector that matches that structure. In many cases, :first-of-type is closer to what you want.
Example:
.home p.red:first-of-type {
border: 1px solid red;
}
This works here because the first <p> inside .home is also the first red paragraph.
However, CSS still cannot directly express “the first element with class red anywhere among siblings” in older selector patterns unless the HTML structure supports it. Selector choice depends on the actual DOM structure.
Mental Model
Think of sibling elements like people standing in a line.
:first-childmeans: this person must be at the very front of the line..red:first-childmeans: this person wears a red badge and is also at the very front of the line.- It does not mean: find the first person in the line who wears a red badge.
In your HTML, the <span> is standing at the front of the line. The first .red paragraph is only the second child overall, so it does not qualify for :first-child.
If you instead ask for p:first-of-type, you are saying:
- find the first person in line who is a
p
That matches the first paragraph, even if a different tag appears before it.
Syntax and Examples
Core syntax
selector:first-child
selector:first-of-type
selector:nth-child(n)
selector:nth-of-type(n)
What your original selector means
.home .red:first-child {
border: 1px solid red;
}
This matches any .red element inside .home only if it is the first child of its parent.
Example 1: Why it fails
<div class="home">
<span>blah</span>
<p class="red">first</p>
<p class="red">second</p>
</div>
.home .red:first-child {
border: 1px solid red;
}
No match happens, because the first child is <span>, not the first red paragraph.
Example 2: Use :first-of-type
.home p.red:first-of-type {
border: 1px solid red;
}
This works for the given HTML because:
- the first
<p>inside.homeis<p class="red">first</p> - that element has class
red
Example 3: If the red element is truly the first child
<div class="home">
<p class="red">first</p>
<p class="red">second</p>
</div>
.home .red:first-child {
border: 1px solid red;
}
Now it matches, because the first .red is also the first child.
Example 4: Modern CSS option with :first-child and direct children
If your structure is predictable, you can target the first child and require the class:
.home > .red:first-child {
border: 1px solid red;
}
This still only works when .red is literally the first child of .home.
Example 5: Select the first paragraph, then require .red
.home > p.red:first-of-type {
border: 1px solid red;
}
This is often the best fit for markup like your example.
Step by Step Execution
Consider this HTML:
<div class="home">
<span>blah</span>
<p class="red">first</p>
<p class="red">second</p>
</div>
And this CSS:
.home .red:first-child {
border: 1px solid red;
}
How the browser evaluates it
-
Find elements inside
.homethat have class.red.<p class="red">first</p><p class="red">second</p>
-
For each of those elements, check whether it is also
:first-child. -
For
<p class="red">first</p>:- Its parent is
.home - The first child of
.homeis<span>blah</span> - So this
<p>is not:first-child
- Its parent is
-
For
<p class="red">second</p>:- It is also not the first child
-
Result:
- nothing matches
Now try this CSS:
.home p.red:first-of-type {
border: 1px solid red;
}
What changes
- Find
pelements inside.homewith classred. - Check whether each one is the
first-of-typeamong its siblings. - The first
<p>inside.homeis:
<p class="red">first</p>
-
That element is both:
- a
<p> - class
red - the first
<p>of its type
- a
-
Result:
- only the first red paragraph gets the border
Real World Use Cases
This kind of selector logic shows up often in real interfaces.
Common scenarios
- Styling the first item in a list differently
- Adding spacing to all cards except the first one
- Highlighting the first error message in a form
- Styling the first article preview or notification
- Targeting the first row, paragraph, or heading in a content block
Example: first notification card
<div class="notifications">
<div class="note important">Server restarted</div>
<div class="note important">Backup complete</div>
</div>
.notifications .important:first-child {
font-weight: bold;
}
This only works if the first .important element is literally the first child.
Example: first paragraph in an article
article p:first-of-type {
font-size: 1.1rem;
}
This is a common and reliable pattern.
Example: avoid unnecessary markup changes
If CSS cannot cleanly express “the first element with a given class” because of the structure, developers often:
- add a helper class like
.first-red - change the HTML structure
- use JavaScript when the selection is dynamic
Real Codebase Usage
In real projects, developers usually avoid fragile selectors when structure may change.
Common patterns
1. Prefer structure-aware selectors
If you know the element type:
.home p.red:first-of-type {
border: 1px solid red;
}
This is clearer than relying on .red:first-child when another tag might appear first.
2. Add explicit classes for important styling hooks
<p class="red first-red">first</p>
.first-red {
border: 1px solid red;
}
This is common in large codebases because it is easy to read and less likely to break.
3. Use direct child selectors when needed
.home > p.red:first-of-type {
border: 1px solid red;
}
This prevents accidental matches deeper in the tree.
4. Keep selectors maintainable
Developers often avoid overly clever CSS because HTML structure changes over time. A selector that depends on exact sibling order can break when another element is inserted.
5. Use JavaScript only when the logic is dynamic
If “first red” depends on user actions or generated content, JavaScript may be more practical than CSS alone.
Common Mistakes
1. Thinking :first-child means “first matching element”
Broken expectation:
.red:first-child {
color: red;
}
This does not mean “the first .red.” It means “a .red element that is also the first child.”
2. Forgetting that other element types count
Broken example:
<div>
<span>before</span>
<p class="red">hello</p>
</div>
p.red:first-child {
color: red;
}
This fails because the <span> is the first child.
3. Confusing :first-child with :first-of-type
Use :first-of-type when you mean the first <p>, first <li>, first <div>, and so on.
p:first-of-type {
color: red;
}
4. Using the wrong selector for nested elements
Broken assumption:
.home .red:first-child
This can match .red elements anywhere inside .home, not just direct children. If you mean direct children, use >:
.home > .red:first-child
5. Expecting CSS to select “first by class” in all cases
CSS is based on document structure, not arbitrary matching history. If you truly need “the first sibling that has class red” regardless of tag and earlier siblings, plain CSS may not be enough depending on browser support and structure.
6. Writing selectors that break when HTML changes
A small markup change like inserting a heading or icon can stop :first-child from matching. Prefer stable hooks when possible.
Comparisons
| Selector | What it means | Works for your HTML? | Notes |
|---|---|---|---|
.red:first-child | Element has class red and is the first child | No | Fails because <span> comes first |
p.red:first-child | A p.red that is the first child | No | Same problem |
p.red:first-of-type | A p.red that is the first p sibling | Yes | Best match for the shown HTML |
.home > .red:first-child | Direct child with class red that is first child | No | Still fails because first child is <span> |
.home > p.red:first-of-type | Direct child p.red that is first p | Yes | More specific and safer |
:first-child vs :first-of-type
| Feature | :first-child | :first-of-type |
|---|---|---|
| Checks position among all siblings | Yes | No |
| Checks position among same tag name only | No | Yes |
| Useful when exact first child matters | Yes | Yes |
| Useful when first paragraph/div/list item matters | No | Yes |
Rule of thumb
- Use
:first-childwhen the element must literally be first. - Use
:first-of-typewhen you mean the first element of a certain tag.
Cheat Sheet
Quick reference
/* Element must literally be the first child */
.red:first-child
/* First <p> among siblings, and it must have class red */
p.red:first-of-type
/* Direct child only */
.home > p.red:first-of-type
Important rules
.red:first-childmeans:- class is
red - and the same element is the first child
- class is
- It does not mean:
- first element with class
red
- first element with class
:first-of-typechecks tag type, not class- Other sibling elements still affect
:first-child - Use
>if you only want direct children
Good fix for the shown HTML
.home p.red:first-of-type {
border: 1px solid red;
}
When this fix works
It works when the first <p> inside .home is also the first red one.
When to use a class instead
If you need a guaranteed styling hook regardless of structure:
<p class="red first-red">first</p>
.first-red {
border: 1px solid red;
}
FAQ
Why doesn't .red:first-child select the first red element?
Because :first-child means the element must be the very first child of its parent, not just the first one with that class.
What selector should I use instead?
For the HTML shown, use:
.home p.red:first-of-type
What is the difference between :first-child and :first-of-type?
:first-childchecks whether the element is first among all siblings.:first-of-typechecks whether it is the first of its tag type, such as the first<p>.
Can CSS select the first element with a class regardless of tag?
Not reliably with simple classic selectors in all structures. CSS is structural, so the exact HTML layout matters.
Should I use JavaScript for this?
Only if the selection is dynamic or CSS cannot express the condition cleanly. In many cases, adding a dedicated class is simpler.
Why does adding a <span> break my selector?
Because :first-child depends on actual sibling order. If another element comes first, your target is no longer the first child.
Is .home > .red:first-child better?
It is more specific because it limits the match to direct children, but it still requires the .red element to be the first child.
Mini Project
Description
Build a small article preview where only the first paragraph with a specific style gets highlighted. This demonstrates the difference between selecting by class and selecting by structural position in CSS.
Goal
Create a content block where the first red paragraph is styled correctly without relying on :first-child incorrectly.
Requirements
- Create a container with at least one non-paragraph element before the paragraphs.
- Add at least three paragraphs with the class
red. - Style only the first red paragraph with a border.
- Keep the other red paragraphs unstyled.
- Use a selector that works with the given structure.
Keep learning
Related questions
Angular ngClass Conditional Class Binding Explained
Learn how to use Angular ngClass for conditional classes, fix common binding mistakes, and understand why this template error happens.
CSS :not() Selector for Elements Without a Class or Attribute
Learn how to use the CSS :not() selector to target elements that do not have a specific class or attribute, with examples and common pitfalls.
CSS Font Scaling Relative to Container Size: %, em, rem, vw, and Responsive Text
Learn how CSS font scaling really works and how to make text responsive using %, em, rem, vw, clamp(), and media queries.