Select The Previous Sibling

Master the CSS :has() pseudo-class to select previous siblings and unlock new styling patterns without JavaScript

The Challenge of Previous Sibling Selection

For years, CSS developers faced a frustrating limitation: there was no way to select previous siblings. You could easily target the next sibling with the adjacent combinator (+), but going backward in the DOM was impossible without JavaScript or creative HTML restructuring. The :has() pseudo-class changed everything, opening up entirely new possibilities for CSS-based styling patterns.

This guide explores how to leverage :has() to select previous siblings, with practical examples you can apply to modern web development projects.


The Game-Changer: CSS :has() Pseudo-Class

The :has() pseudo-class is a relational selector that checks for descendants or siblings. Part of the CSS Selectors Level 4 specification, :has() now enjoys broad support across all modern browsers, enabling "reverse" selection patterns that were previously impossible.

/* Select .box elements that are immediately followed by .circle */
.box:has(+ .circle) {
 background-color: #e0f2fe;
 border-color: #0284c7;
}

This selector finds all .box elements, filters to only those matching "self + .circle", and returns the .box that precedes the .circle. Understanding how these CSS selectors work opens up powerful new approaches to component styling.

Key Capabilities of Previous Sibling Selection

Immediate Previous Sibling

Target the element immediately before another using :has() with the adjacent sibling combinator (+)

Nth Previous Sibling

Select elements further back in the DOM by chaining multiple adjacent combinators

All Preceding Siblings

Use the general sibling combinator (~) to select every element that comes before a reference

Conditional Styling

Create dynamic UI patterns based on sibling relationships without JavaScript

Selecting the Immediate Previous Sibling

The fundamental pattern for selecting the previous sibling combines :has() with the adjacent sibling combinator:

/* Select .box elements that are immediately followed by .circle */
.box:has(+ .circle) {
 background-color: #e0f2fe;
 border-color: #0284c7;
}

This selector works by:

  1. Finding all .box elements in the document
  2. Filtering to only those that match the pattern "self + .circle"
  3. Returning the .box that precedes the .circle

Example HTML Structure

<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="circle"></div>
<div class="box"></div>

The selector will target the third .box (the one immediately before .circle).

This technique works seamlessly with CSS modules for component-scoped styling, keeping your selectors isolated and maintainable.

Selecting the Nth Previous Sibling

For selecting siblings that are not immediately adjacent, add more adjacent combinators:

/* Select .box that is 2 siblings before .circle */
.box:has(+ * + .circle) {
 background-color: #fef3c7;
 border-color: #d97706;
}

/* Select .box that is 3 siblings before .circle */
.box:has(+ * + * + .circle) {
 background-color: #fce7f3;
 border-color: #db2777;
}

The wildcards (*) represent intermediate elements between the target and the reference element. You can chain as many combinators as needed for your use case. This approach gives you precise control similar to CSS typed arithmetic for programmatic styling decisions.

Selecting All Preceding Siblings

Combine :has() with the general sibling combinator (~) to select all elements that come before a reference element:

/* Select all .box elements that precede a .circle anywhere */
.box:has(~ .circle) {
 background-color: #ede9fe;
 border-color: #7c3aed;
}

Selective Preceding Siblings

To select all preceding siblings except the immediately adjacent one:

/* Select .box elements before .circle, but not the one right before */
.box:has(~ * + .circle) {
 background-color: #f0fdf4;
 border-color: #16a34a;
}

Form Validation

Highlight input fields when the next field has validation errors

Table Row Styling

Add emphasis to rows that precede total or summary rows

Card Layouts

Add spacing after cards that precede CTA cards

Navigation States

Style nav items before the active item for visual flow

Performance Considerations

The :has() pseudo-class is evaluated during style calculation, similar to other CSS selectors. Here are key performance guidelines:

Best Practices

  • Keep selector chains short: Deeply nested :has() chains may impact initial render
  • Use specific element types: Avoid universal selectors (*) when possible
  • Test on target devices: Complex :has() patterns should be tested across your supported browsers
  • Avoid in animations: Don't use :has() inside @keyframes animations

Browser Optimization

Modern browser engines optimize :has() queries progressively, making them performant for typical UI patterns. The selector is generally fast enough for production use in interactive components.


Best Practices and Common Pitfalls

Do

  • Use specific selectors rather than generic wildcards
  • Test across target browsers and devices
  • Combine with feature queries (@supports) for graceful degradation
  • Keep selector intent clear and maintainable

Don't

  • Chain too many :has() selectors (creates complexity)
  • Rely on :has() for critical layout-dependent styles
  • Use :has() with pseudo-elements (not supported)
  • Nest :has() inside :has() (not permitted by specification)

Frequently Asked Questions

Conclusion

The ability to select previous siblings with CSS :has() represents a fundamental shift in what's possible with pure CSS. What once required JavaScript or creative DOM restructuring can now be achieved with elegant, maintainable selectors.

As browser support continues to grow and developers explore these patterns, we'll see more sophisticated UI patterns emerge that leverage the full power of relational selectors. Start incorporating :has() into your projects today to create responsive, interactive interfaces without relying on JavaScript for style-related functionality.


Related Resources:

Need Help Building Modern Web Interfaces?

Our team specializes in creating performant, accessible websites using the latest CSS techniques and modern web development practices.

Sources

  1. MDN Web Docs - :has() Selector - Official CSS specification documentation
  2. Tobias Ahlin - Selecting previous siblings with CSS :has() - Practical examples with visual demos
  3. MDN Web Docs - Next-sibling combinator - Adjacent sibling combinator documentation