Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten.Erfahre mehr über dieses Experiment.
:has()
Baseline 2023Newly available
Since December 2023, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.
Die funktionale:has()CSSPseudoklasse repräsentiert ein Element, wenn einer der als Argument übergebenenrelativen Selektoren mindestens ein Element selektiert, wenn er an diesem Element verankert ist. Diese Pseudoklasse bietet eine Möglichkeit, ein Elternelement oder ein vorheriges Geschwisterelement in Bezug auf ein Bezugselement zu selektieren, indem sie einerelative Selektorenliste als Argument verwendet.
/* Selects an h1 heading with aparagraph element that immediately followsthe h1 and applies the style to h1 */h1:has(+ p) { margin-bottom: 0;}Die:has()-Pseudoklasse übernimmt dieSpezifität des spezifischsten Selektors in ihren Argumenten, genauso wie:is() und:not() dies tun.
In diesem Artikel
Syntax
:has(<relative-selector-list>) { /* ... */}Falls die:has()-Pseudoklasse in einem Browser nicht unterstützt wird, schlägt der gesamte Selektorblock fehl, es sei denn,:has() befindet sich in einer toleranten Selektorenliste, wie in:is() und:where().
Die:has()-Pseudoklasse kann nicht in einer anderen:has() eingebettet werden.
Pseudoelemente sind ebenfalls keine gültigen Selektoren innerhalb von:has() und Pseudoelemente sind keine gültigen Anker für:has(). Dies liegt daran, dass viele Pseudoelemente bedingt existieren, basierend auf dem Styling ihrer Vorfahren, und das Zulassen dieser zur Abfrage durch:has() kann zirkuläre Abfragen einführen.
Beispiele
>Selektieren eines Elternelements
Sie suchen möglicherweise nach einem "Eltern-Kombinator", der es Ihnen ermöglicht, im DOM-Baum nach oben zu gehen und das Elternelement eines spezifischen Elements auszuwählen. Die:has()-Pseudoklasse tut dies, indem sieparent:has(child) (für jedes Elternteil) oderparent:has(> child) (für direkte Elternteile) verwendet. Dieses Beispiel zeigt, wie ein<section>-Element gestylt wird, wenn es ein Kind mit derfeatured-Klasse enthält.
<section> <article>Featured content</article> <article>Regular content</article></section><section> <article>Regular content</article></section>section:has(.featured) { border: 2px solid blue;}Ergebnis
Mit dem Geschwister-Kombinator
Die:has()-Stildeklaration im folgenden Beispiel passt den Abstand nach<h1>-Überschriften an, wenn sie unmittelbar von einer<h2>-Überschrift gefolgt werden.
HTML
<section> <article> <h1>Morning Times</h1> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p> </article> <article> <h1>Morning Times</h1> <h2>Delivering you news every morning</h2> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p> </article></section>CSS
section { display: flex; align-items: start; justify-content: space-around;}article { display: inline-block; width: 40%;}h1,h2 { font-size: 1.2em;}h2 { font-size: 1em; color: rgb(150 149 149);}h1,h2 { margin: 0 0 1rem 0;}h1:has(+ h2) { margin: 0 0 0.25rem 0;}Ergebnis
Dieses Beispiel zeigt zwei ähnliche Texte nebeneinander zum Vergleich – den linken mit einerH1-Überschrift gefolgt von einem Absatz und den rechten mit einerH1-Überschrift gefolgt von einerH2-Überschrift und dann einem Absatz. Im Beispiel rechts hilft:has(), dasH1-Element auszuwählen, das unmittelbar von einemH2-Element (angezeigt durch den nächsten Geschwister-Kombinator+) gefolgt wird, und die CSS-Regel verringert den Abstand nach einem solchenH1-Element. Ohne die:has()-Pseudoklasse können Sie keine CSS-Selektoren verwenden, um ein vorhergehendes Geschwisterelement eines anderen Typs oder ein Elternelement auszuwählen.
Mit der :is() Pseudoklasse
Dieses Beispiel baut auf dem vorherigen auf, um zu zeigen, wie man mehrere Elemente mit:has() auswählt.
HTML
<section> <article> <h1>Morning Times</h1> <h2>Delivering you news every morning</h2> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p> </article> <article> <h1>Morning Times</h1> <h2>Delivering you news every morning</h2> <h3>8:00 am</h3> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p> </article></section>CSS
section { display: flex; align-items: start; justify-content: space-around;}article { display: inline-block; width: 40%;}h1 { font-size: 1.2em;}h2 { font-size: 1em; color: rgb(150 149 149);}h3 { font-size: 0.9em; color: darkgrey;}h1,h2,h3 { margin: 0 0 1rem 0;}:is(h1, h2, h3):has(+ :is(h2, h3, h4)) { margin: 0 0 0.25rem 0;}Ergebnis
Hier wird die erste:is() Pseudoklasse verwendet, um eines der Überschriftelemente in der Liste auszuwählen. Die zweite:is()-Pseudoklasse wird verwendet, um eine Liste von nächsten Geschwisterselektoren als Argument an:has() zu übergeben. Die:has()-Pseudoklasse hilft, jedesH1,H2 oderH3-Element auszuwählen, das unmittelbar von (angezeigt durch+) einemH2,H3 oderH4-Element gefolgt wird, und die CSS-Regel verringert den Abstand nach solchenH1,H2 oderH3-Elementen.
Dieser Selektor könnte auch so geschrieben werden:
:is(h1, h2, h3):has(+ h2, + h3, + h4) { margin: 0 0 0.25rem 0;}Logische Operationen
Der:has() relationale Selektor kann verwendet werden, um zu überprüfen, ob eines von mehreren Merkmalen zutrifft oder ob alle Merkmale zutreffen.
Indem Sie Komma-getrennte Werte innerhalb des:has() relationalen Selektors verwenden, prüfen Sie, ob eines der Parameter existiert.x:has(a, b) wirdx stylen, wenn Nachkommena ODERb existieren.
Indem Sie mehrere:has() relationale Selektoren miteinander verknüpfen, prüfen Sie, ob alle Parameter existieren.x:has(a):has(b) wirdx stylen, wenn Nachkommena UNDb existieren.
body:has(video, audio) { /* styles to apply if the content contains audio OR video */}body:has(video):has(audio) { /* styles to apply if the content contains both audio AND video */}Analogie zwischen :has() und regulären Ausdrücken
Interessanterweise können wir einige CSS:has()-Konstrukte mit derLookahead Assertion in regulären Ausdrücken in Zusammenhang bringen, da beide es Ihnen ermöglichen, Elemente (oder Zeichenfolgen in regulären Ausdrücken) basierend auf einer Bedingung auszuwählen, ohne tatsächlich das die Bedingung erfüllende Element (oder Zeichenfolge) selbst auszuwählen.
Positiver Lookahead (?=pattern)
Im regulären Ausdruckabc(?=xyz) wird die Zeichenfolgeabc nur dann übereinstimmend gefunden, wenn sie unmittelbar von der Zeichenfolgexyz gefolgt wird. Da es sich um eine Lookahead-Operation handelt, istxyz nicht in der Übereinstimmung enthalten.
Das analoge Konstrukt in CSS wäre.abc:has(+ .xyz): es selektiert das Element.abc nur, wenn ein nächstes Geschwisterelement.xyz vorhanden ist. Der Teil:has(+ .xyz) fungiert als Lookahead-Operation, da das Element.abc und nicht das Element.xyz ausgewählt wird.
Negativer Lookahead (?!pattern)
Ähnlich verhält es sich im Fall des negativen Lookaheads, im regulären Ausdruckabc(?!xyz), wird die Zeichenfolgeabc nur dann übereinstimmend gefunden, wenn sienicht vonxyz gefolgt wird. Das analoge CSS-Konstrukt.abc:has(+ :not(.xyz)) selektiert das Element.abc nicht, wenn das nächste Element.xyz ist.
Leistungserwägungen
Bestimmte Verwendungen der:has()-Pseudoklasse können die Seitenleistung erheblich beeinflussen, insbesondere bei dynamischen Updates (DOM-Mutationen). Browser-Engines müssen die:has()-Selektoren neu bewerten, wenn sich das DOM ändert, und komplexe oder schlecht eingeschränkte Selektoren können zu kostenintensiven Berechnungen führen.
Vermeiden Sie breite Verankerung
Der Ankerselektor (dasA inA:has(B)) sollte kein Element sein, das zu viele Kinder hat, wiebody,:root oder*. Das Verankern von:has() an sehr allgemeinen Selektoren kann die Leistung beeinträchtigen, weil jede DOM-Änderung innerhalb des gesamten Unterbaums eines breit ausgewählten Elements den Browser zwingt, die:has()-Bedingung erneut zu überprüfen.
/* Avoid anchoring :has() to broad elements */body:has(.sidebar) { /* styles */}:root:has(.content) { /* styles */}*:has(.item) { /* styles */}Stattdessen sollte:has() an spezifische Elemente wie.container oder.gallery verankert werden, um den Umfang zu reduzieren und die Leistung zu verbessern.
/* Use specific containers to limit scope */.container:has(.sidebar-expanded) { /* styles */}.content-wrapper:has(> article[data-priority="high"]) { /* styles */}.gallery:has(> img[data-loaded="false"]) { /* styles */}Minimieren von Unterbaum-Traversalen
Der innere Selektor (dasB inA:has(B)) sollte Kombinatoren wie> oder+ verwenden, um die Traversierung zu begrenzen. Wenn der Selektor innerhalb von:has() nicht eng eingeschränkt ist, muss der Browser möglicherweise den gesamten Unterbaum des Ankerelements bei jeder DOM-Änderung durchlaufen, um zu überprüfen, ob die Bedingung noch zutrifft.
In diesem Beispiel erfordert jede Änderung innerhalb von.ancestor die Überprüfung aller Nachkommen auf.foo:
/* May trigger full subtree traversal */.ancestor:has(.foo) { /* styles */}Die Verwendung von Kind- oder Geschwisterkombinatoren begrenzt den Umfang des inneren Selektors und reduziert die Leistungskosten von DOM-Mutationen. In diesem Beispiel muss der Browser nur direkte Kinder oder die Nachkommen eines bestimmten Geschwisters überprüfen:
/* More constrained - limits traversal */.ancestor:has(> .foo) { /* direct child */}.ancestor:has(+ .sibling .foo) { /* descendant of adjacent sibling */}Bestimmte innere Selektoren können den Browser zwingen, bei jeder DOM-Änderung die Ahnenkette nach potenziellen Ankern zu durchsuchen, die aktualisiert werden müssen. Dies passiert, wenn die Struktur impliziert, dass Ahnen der geänderten Elemente überprüft werden müssen.
In diesem Beispiel erfordert jede DOM-Änderung die Überprüfung, ob das geänderte Element ein beliebiges Element (*) ist, das ein direkter Nachkomme von.foo ist und ob sein Elternteil (oder weitere Vorfahren).ancestor sind.
/* Might trigger ancestor traversal */.ancestor:has(.foo > *) { /* styles */}Das Einschränken des inneren Selektors mit spezifischen Klassen oder direkten Kind-Kombinatoren (z. B..specific-child im nächsten Snippet) reduziert teure Ahnen-Traversalen, indem die Überprüfung des Browsers auf ein gut definiertes Element beschränkt wird und so die Leistung verbessert wird.
/* Constrain the inner selector to avoid ancestor traversals */.ancestor:has(.foo > .specific-child) { /* styles */}Hinweis:Diese Leistungsmerkmale können sich verbessern, wenn Browser:has()-Implementierungen optimieren, aber die grundlegenden Einschränkungen bleiben::has() muss einen ganzen Unterbaum durchlaufen, daher ist die Minimierung der Größe des Unterbaums erforderlich. In einem Selektor wieA:has(B) stellen Sie sicher, dass IhrA nicht zu viele Kinder hat und dass IhrB eng gefasst ist, um unnötige Traversierungen zu vermeiden.
Spezifikationen
| Specification |
|---|
| Selectors Level 4> # relational> |