CSS :has() Selector Not Supported Fix
In this tutorial, you'll learn about CSS :has() Selector Not Supported Fix. We cover key concepts, practical examples, and best practices.
The Problem
The CSS :has() relational selector lets you style a parent element based on its children. Older browsers do not support it, and incorrect usage (like nesting :has() inside :has() or using it where it is not allowed) causes the entire rule to fail.
Quick Fix
Step 1: Provide fallback for unsupported browsers
/* Wrong — no fallback for browsers without :has() */
.card:has(img) {
grid-column: span 2;
}
/* Right — enhance with :has(), keep baseline styles */
.card {
grid-column: span 1;
}
@supports selector(:has(*)) {
.card:has(img) {
grid-column: span 2;
}
}
Step 2: Use :has() to style parent based on child state
/* Wrong — cannot select parent based on child */
.form input:invalid {
border-color: red; /* Only styles the input, not the parent */
}
/* Right — style the parent based on child state */
.form:has(input:invalid) {
border: 2px solid red;
padding: 1rem;
}
.form:has(input:valid) {
border: 2px solid green;
padding: 1rem;
}
Step 3: Avoid forbidden :has() usages
/* Wrong — :has() inside pseudo-elements not allowed */
.element::after:has(.child) {
content: 'has child';
}
/* Wrong — :has() inside :has() may cause performance issues */
.parent:has(:has(.child)) {
color: red;
}
/* Right — flatten the selector */
.parent:has(.child) {
color: red;
}
Step 4: Use :has() for quantity queries
/* Wrong — no way to count items without JS */
.list-item { width: 100%; }
/* Right — use :has() for quantity-based styling */
.list:has(> :nth-child(n+5)) .list-item {
width: 50%;
}
.list:has(> :nth-child(n+10)) .list-item {
width: 33.33%;
}
Step 5: Style siblings based on adjacent state
/* Wrong — cannot select next sibling based on previous */
.input:focus + .label { color: blue; }
/* Right — use :has() to target any sibling */
.form-group:has(.input:focus) .label {
color: blue;
font-weight: bold;
}
Prevention
- Always provide baseline styles before
:has()enhancements - Use
@supports selector(:has(*))to detect support - Avoid nesting
:has()inside:has() - Do not use
:has()inside pseudo-elements - Test in target browsers to ensure fallback behavior
Common Mistakes with has selector
- Forgetting that lazy evaluation defers computation until the value is forced, causing space leaks with unevaluated thunks
- Using
returnto exit a function early instead of wrapping a pure value in the monad - Mixing let bindings with <- bindings in do notation, producing type errors
These mistakes appear frequently in real-world CSS code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro