Snippets /

:has() dropdown

Style the parent based on child state — the CSS parent selector.

:has() on form fields too:

Widely supported
uino-js

Quick implementation

/* 1. Highlight the trigger when dropdown is open */
.nav-item:has([open]) summary {
  background: oklch(0.92 0.06 265);
  border-color: oklch(0.52 0.22 265 / 0.4);
  color: oklch(0.52 0.22 265);
}

/* 2. Reveal the menu */
.nav-item .menu {
  opacity: 0;
  pointer-events: none;
  transform: translateY(-4px);
  transition: opacity 0.15s, transform 0.15s;
}
.nav-item:has([open]) .menu {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

/* 3. Highlight a form wrapper when a child input is focused */
.input-group:has(input:focus-within) {
  border-color: oklch(0.52 0.22 265);
  box-shadow: 0 0 0 3px oklch(0.52 0.22 265 / 0.15);
}

/* Uses <details>/<summary> for open state — no JS needed */

Prompt this to your LLM

Includes nav dropdown and form highlight patterns, plus a React variant.

You are a senior frontend engineer specializing in modern CSS.

Goal: Build two :has() patterns in a single demo — a nav dropdown and a form field highlight.

Pattern 1 — Nav dropdown:
- Use <details> + <summary> for the trigger and open state (no JS needed).
- Use .nav-item:has([open]) summary { ... } to highlight the trigger when open.
- Use .nav-item:has([open]) .menu { opacity: 1; pointer-events: auto; } to show the menu.
- Animate the menu with opacity + translateY using transition.

Pattern 2 — Form field focus highlight:
- Use .input-group:has(input:focus-within) to highlight the entire field wrapper (not just the input) when focused.
- This replaces a JS "add class on focus" pattern.

Technical constraints:
- Use oklch() for all colors.
- :has() is widely supported — no polyfill needed.
- The demo should be self-contained.

Framework variant (pick one):
A) Vanilla HTML + CSS.
B) React — DropdownMenu component (summary + details) and FormField component with wrapper highlight via CSS only.

Edge cases:
- Multiple dropdowns open simultaneously: details/summary allows this by default. Note that a single-open constraint would require JS.
- The .menu should be position: absolute with a z-index to float above other content.

Return the full HTML + CSS.

Why this matters in 2026

:has() is the long-awaited parent selector. Before it, you couldn't style an ancestor based on its descendants — you needed JavaScript to add/remove classes. Now a single selector handles it: highlight a card when any internal image is hovered, show a menu when details is open, outline a form wrapper when any child input is focused.

Combined with details/summary for open/close state, you eliminate an entire category of JS patterns from your codebase.

The logic

.parent:has(.child-state) selects .parent when it contains a matching .child-state. With details[open], the [open] attribute is set by the browser when the disclosure is open. So .nav-item:has([open]) matches the nav item whenever its details is open — no JS, no class toggle.

The form pattern :has(input:focus-within) fires when any input inside the wrapper gains focus. The wrapper's border and shadow update in CSS, giving a polished field-focus effect that used to require event listeners.

Accessibility & performance

details/summary is keyboard accessible: Enter/Space toggles, and screen readers announce "expanded"/"collapsed". Don't trap focus inside the dropdown — let the browser close it on Escape. :has() is well optimized in modern engines; use specific selectors rather than broad ones (e.g. avoid :has(*)).