:has() relational selector

Baseline 2023 (Chrome 105, Safari 15.4, Firefox 121); breit verfügbar.

Chrome 105Edge 105Safari 15.4Firefox 121

Wählt ein Element danach aus, was es enthält oder was ihm folgt, was CSS vorher nie konnte ("eine Karte, die ein Bild hat", "ein Formularfeld, dessen Input ungültig ist", "das Label vor einer angehakten Checkbox"). Ersetzt eine große Klasse von JS-Zustandsklassen.

Shipping
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; }
HTML
<form class="fx-002">
  <label><input type="checkbox"> Enable shipping address</label>
  <fieldset><legend>Shipping</legend><input placeholder="Street" required></fieldset>
</form>

Fallback: In `@supports selector(:has(a))` einpacken, wenn der Zustand ohne :has anders aussehen muss; sonst bleibt das fieldset einfach aktiv.

Quelle: developer.mozilla.org/en-US/docs/Web/CSS/:has

Prompt

Nutze `:has()` für eltern- und geschwisterbewusstes Styling, statt Klassen per JavaScript umzuschalten: z. B. `form:has(input[type=checkbox]:checked) fieldset`, um einen Abschnitt einzublenden, `.card:has(img)` für Medienvarianten, `label:has(+ input:focus-visible)` für fokussierte Labels. Halte das Argument von `:has()` flach (ein oder zwei zusammengesetzte Selektoren) für die Performance und sichere nicht-triviale Layouts mit `@supports selector(:has(a))` ab.