I have multiple elements with the class name “red”, but I’m unable to select the first element with class=“red” using the CSS rule .home .red:first-child. Here’s my HTML structure:
<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>
What’s incorrect with my CSS selector and how can I modify it to target specifically the first child element with the class “red”?
The issue with your CSS selector .home .red:first-child is that :first-child doesn’t select the first element that has the class “red” - it selects the first child element of the parent if that element also has the class “red”. In your HTML, the first child is <span>blah</span>, which doesn’t have the class “red”, so the selector doesn’t match anything.
To target specifically the first element with class=“red”, you need to use different CSS pseudo-classes that match your intended behavior.
Contents
- Understanding the Problem with :first-child
- Solution 1: Using :first-of-type
- Solution 2: Using CSS4 :nth-child() Syntax
- Solution 3: Using the General Sibling Combinator
- Solution 4: Adding a Class Programmatically
- Comparison of Solutions
- Best Practices and Recommendations
Understanding the Problem with :first-child
The :first-child pseudo-class represents the first element among a group of sibling elements, but it only selects an element IF it is both:
- The first child of its parent, AND
- Matches the rest of the selector
In your HTML structure:
<div class="home">
<span>blah</span> <!-- This is the first child -->
<p class="red">first</p> <!-- This is the first element with class "red" -->
<p class="red">second</p>
<p class="red">third</p>
<p class="red">fourth</p>
</div>
The selector .home .red:first-child fails because the first child <span> doesn’t have the class “red”, so the condition isn’t met.
Key insight: According to the Mozilla Developer Network, “:first-child selects the first element among a group of sibling elements” but only if it matches the selector conditions.
Solution 1: Using :first-of-type
The :first-of-type pseudo-class selects the first element of a specific type within its parent, regardless of whether other elements come before it.
.home .red:first-of-type {
color: red;
/* other styles */
}
This works because :first-of-type looks for the first <p> element within .home that also has the class “red”. Since the first <p> element in your structure has the class “red”, this selector will match it.
However, be aware that :first-of-type has limitations - it’s based on element type (tag name), not class. If you had other <p> elements without the “red” class before your first “red” <p>, it wouldn’t work as expected.
Solution 2: Using CSS4 :nth-child() Syntax
CSS Selectors Level 4 introduced support for using selectors inside :nth-child(). This is the most direct way to solve your problem:
.home :nth-child(1 of .red) {
color: red;
/* other styles */
}
This syntax means "select the 1st child that matches the selector .red within .home. This is exactly what you’re trying to achieve.
Browser support: This syntax is supported in modern browsers including Chrome 88+, Firefox 75+, Safari 14.1+, and Edge 88+.
For older browsers that don’t support this syntax, you can use a combination approach:
/* For modern browsers */
.home :nth-child(1 of .red) {
color: red;
}
/* Fallback for older browsers */
.home .red:not(.home .red ~ .red) {
color: red;
}
Solution 3: Using the General Sibling Combinator
You can use the general sibling combinator (~) to select the first element with a specific class by excluding all subsequent siblings with the same class:
.home .red:not(.home .red ~ .red) {
color: red;
/* other styles */
}
This works because:
.home .redselects all elements with class “red” inside “.home”.home .red ~ .redselects all elements with class “red” that come after the first one:not()excludes those subsequent elements- The result is only the first element with class “red”
While this works, it can be less performant than other methods and may be harder to read and maintain.
Solution 4: Adding a Class Programmatically
Sometimes the simplest solution is to add a specific class to the first element programmatically, either through JavaScript or by modifying your HTML:
HTML modification:
<div class="home">
<span>blah</span>
<p class="red first-red">first</p>
<p class="red">second</p>
<p class="red">third</p>
<p class="red">fourth</p>
</div>
CSS:
.home .first-red {
color: red;
/* other styles */
}
JavaScript approach (if you can’t modify HTML):
// This would run when the page loads
document.addEventListener('DOMContentLoaded', function() {
const firstRed = document.querySelector('.home .red');
if (firstRed) {
firstRed.classList.add('first-red');
}
});
This approach gives you the most control and performance, but requires additional code.
Comparison of Solutions
| Solution | Browser Support | Performance | Readability | Flexibility |
|---|---|---|---|---|
.red:first-of-type |
Excellent | Good | Good | Limited (type-based) |
:nth-child(1 of .red) |
Good (modern browsers) | Excellent | Excellent | Excellent |
.red:not(.red ~ .red) |
Excellent | Poor | Fair | Good |
| Adding class | Excellent | Excellent | Excellent | Excellent |
Best Practices and Recommendations
-
For modern projects: Use
:nth-child(1 of .red)as it’s the most semantic and readable solution. -
For maximum browser compatibility: Add a class programmatically to the first element with JavaScript.
-
For simple cases: Use
:first-of-typeif you’re only dealing with element types and don’t need class-specific selection. -
Avoid: The general sibling combinator approach (
~) due to performance issues and poor readability. -
Consider accessibility: When styling the first element differently, ensure you’re not breaking the visual flow or causing accessibility issues.
-
Test thoroughly: Different solutions may work better in different contexts, so test your chosen approach with your specific HTML structure.
The key takeaway is understanding that :first-child doesn’t work the way many developers intuitively expect - it doesn’t select the first element that matches your selector conditions, but rather selects the first child element IF it happens to match your selector conditions.
Sources
- MDN Web Docs - :first-child pseudo-class
- MDN Web Docs - :first-of-type pseudo-class
- Stack Overflow - CSS selector for first element with class
- BrowserStack Guide - CSS First Item Selector
- CSS-Tricks - :first-of-type
- Weekend Projects - CSS :first-child not working correctly
Conclusion
The .home .red:first-child selector fails because :first-child only matches elements that are both the first child of their parent AND match the rest of the selector. In your case, the first child is a <span> without the “red” class.
To target specifically the first element with class=“red”, you have several effective options:
- Use
:nth-child(1 of .red)for the most direct and readable solution - Add a class programmatically for maximum control and compatibility
- Use
:first-of-typeif you’re working with element types rather than classes - Avoid complex selector combinations that hurt performance
Understanding how CSS pseudo-classes work - specifically that they evaluate the element against the selector conditions rather than filtering elements and then applying pseudo-classes - is crucial for writing effective CSS selectors.