# :has() relational selector

Status: Baseline 2023 (Chrome 105, Safari 15.4, Firefox 121); widely available.  
Source: https://developer.mozilla.org/en-US/docs/Web/CSS/:has  
Page: https://designforai.dev/css/has-relational-selector

Selects an element based on what it contains or what follows it, which CSS never could before ("a card that has an image", "a form field whose input is invalid", "the label before a checked checkbox"). It replaces a large class of JS state classes.

## HTML

```html
<form class="fx-002">
  <label><input type="checkbox"> Enable shipping address</label>
  <fieldset><legend>Shipping</legend><input placeholder="Street" required></fieldset>
</form>
```

## CSS

```css
.fx-002 {
  font-family: system-ui;
  display: grid;
  gap: 12px;
  max-width: 360px
}
.fx-002 fieldset {
  opacity: .4;
  pointer-events: none;
  transition: opacity .2s
}
.fx-002:has(input[type=checkbox]:checked) fieldset {
  opacity: 1;
  pointer-events: auto
}
.fx-002 fieldset:has(input:user-invalid) {
  border-color: #c0392b
}
.fx-002 :is(a,button,input,select,textarea):focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
```

Fallback: Wrap in `@supports selector(:has(a))` if the non-:has state must differ; otherwise the fieldset simply stays enabled.

## Prompt

Use `:has()` for parent- and sibling-aware styling instead of toggling classes with JavaScript: e.g. `form:has(input[type=checkbox]:checked) fieldset` to reveal a section, `.card:has(img)` for media variants, `label:has(+ input:focus-visible)` for focused labels. Keep the `:has()` argument shallow (one or two compound selectors) for performance and guard non-trivial layouts with `@supports selector(:has(a))`.
