Die Pseudo-Klasse :has() ist, ohne Frage, mein neues Lieblings-CSS-Feature. Ich weiß, dass es für viele von Ihnen auch so ist, zumindest für diejenigen unter Ihnen, die die State of CSS-Umfrage durchgeführt haben. Die Möglichkeit, Selektoren umgekehrt zu schreiben, gibt uns mehr Superkräfte, an die ich nie gedacht hätte.
Ich sage „mehr Superkräfte“, weil es bereits eine Menge wirklich erstaunlicher, cleverer Ideen von einer Reihe superkluger Leute gab, wie zum Beispiel
- Verwendung von
:has()als CSS-Elternselektor und vieles mehr von Jen Simmons - Mengenabfragen für „Inseln von Elementen“ mit derselben Klasse, dank CSS
:has()von Bramus - Stilisieren Sie ein Elternelement basierend auf der Anzahl seiner Kinder von Bramus
- Verwendung von Kombinatoren in
:has()von Manuel Matuzović - 4 Möglichkeiten, wie CSS
:has()Ihre HTML-Formulare noch besser machen kann von Austin Gil - Video: Praktische Anwendungsfälle für die Pseudo-Klasse
:has()von Zoran Jambor :has(): der Familienselektor von Jhey Tompkins
Dieser Artikel ist kein endgültiger Leitfaden für :has(). Er soll auch nicht wiederholen, was bereits gesagt wurde. Es ist nur ich (Hallo 👋), der für einen Moment auf den Zug aufspringt, um einige der Wege zu teilen, wie ich :has() wahrscheinlich in meiner täglichen Arbeit verwenden werde ... sobald die Browserunterstützung gut genug ist. (Firefox ist der letzte Ausreißer, wird es aber unterstützen, was unmittelbar bevorsteht.)
Wenn es soweit ist, können Sie darauf wetten, dass ich :has() überall verwenden werde. Hier sind einige reale Beispiele von Dingen, die ich kürzlich gebaut habe und dachte mir: „Mensch, das wird so viel schöner, wenn :has() vollständig unterstützt wird.“
Vermeiden Sie es, über Ihre JavaScript-Komponente hinauszugreifen
Haben Sie jemals eine interaktive Komponente erstellt, die manchmal Stile an anderer Stelle auf der Seite beeinflussen muss? Nehmen Sie das folgende Beispiel, bei dem <nav> ein Mega-Menü ist und dessen Öffnen die Farben des <header>-Inhalts darüber ändert.
Ich habe das Gefühl, dass ich so etwas *ständig* tun muss.
Dieses spezielle Beispiel ist eine React-Komponente, die ich für eine Website erstellt habe. Ich musste mit document.querySelector(...) „außerhalb“ des React-Teils der Seite greifen und eine Klasse auf dem <body>, <header> oder einer anderen Komponente umschalten. Das ist nicht das Ende der Welt, aber es fühlt sich schon etwas doof an. Selbst auf einer reinen React-Website (z. B. einer Next.js-Website) müsste ich mich entscheiden, ob ich einen menuIsOpen-Zustand weiter oben im Komponentenbaum verwalte oder die gleiche DOM-Elementauswahl durchführe – was nicht sehr React-artig ist.
Mit :has() verschwindet das Problem
header:has(.megamenu--open) {
/* style the header differently if it contains
an element with the class ".megamenu--open"
*/
}
Kein Herumfummeln mehr mit anderen Teilen des DOM in meinen JavaScript-Komponenten!
Bessere Tabellen-Striping-UX
Das Hinzufügen von abwechselnden Zeilen „Streifen“ zu Ihren Tabellen kann eine schöne UX-Verbesserung sein. Sie helfen Ihren Augen, den Überblick zu behalten, auf welcher Zeile Sie sich befinden, wenn Sie die Tabelle durchsuchen.
Aber meiner Erfahrung nach funktioniert das bei Tabellen mit nur zwei oder drei Zeilen nicht gut. Wenn Sie zum Beispiel eine Tabelle mit drei Zeilen in <tbody> haben und jede „gerade“ Zeile „streifen“, könnten Sie am Ende nur einen Streifen haben. Das ist ein Muster nicht wirklich wert und könnte Benutzer dazu bringen, sich zu fragen, was an dieser einen hervorgehobenen Zeile so besonders ist.
Unter Verwendung dieser Technik, bei der Bramus :has() verwendet, um Stile basierend auf der Anzahl der Kinder anzuwenden, können wir Tabellenstreifen anwenden, wenn es mehr als sagen wir drei Zeilen gibt.
Möchten Sie es noch ausgefallener gestalten? Sie könnten sich auch entscheiden, dies nur zu tun, wenn die Tabelle mindestens eine bestimmte Anzahl von Spalten hat.
table:has(:is(td, th):nth-child(3)) {
/* only do stuff if there are three or more columns */
}
Entfernen Sie bedingte Klassenlogik aus Vorlagen
Ich muss oft ein Seitenlayout ändern, je nachdem, was auf der Seite vorhanden ist. Nehmen Sie das folgende Grid-Layout, bei dem sich die Platzierung des Hauptinhalts je nach vorhandenem Sidebar in Grid-Bereichen ändert.

Das kann davon abhängen, ob Geschwisterseiten im CMS eingestellt sind. Normalerweise würde ich dies mit Vorlagenlogik tun, um bedingt BEM-Modifikatorklassen zum Layout-Wrapper hinzuzufügen, um beide Layouts zu berücksichtigen. Dieser CSS-Code könnte ungefähr so aussehen (responsive Regeln und anderes Zeug der Kürze halber weggelassen)
/* m = main content */
/* s = sidebar */
.standard-page--with-sidebar {
grid-template-areas: 's s s m m m m m m m m m';
}
.standard-page--without-sidebar {
grid-template-areas: '. m m m m m m m m m . .';
}
CSS-technisch ist das natürlich völlig in Ordnung. Aber es macht den Vorlagencode etwas unübersichtlich. Je nach Ihrer Vorlagensprache kann es ziemlich hässlich werden, bedingt eine Reihe von Klassen hinzuzufügen, besonders wenn Sie dies auch mit vielen Kindelementen tun müssen.
Im Gegensatz dazu ein Ansatz, der auf :has() basiert
/* m = main content */
/* s = sidebar */
.standard-page:has(.sidebar) {
grid-template-areas: 's s s m m m m m m m m m';
}
.standard-page:not(:has(.sidebar)) {
grid-template-areas: '. m m m m m m m m m . .';
}
Ehrlich gesagt, das ist CSS-technisch nicht viel besser. Aber das Entfernen der bedingten Modifikatorklassen aus der HTML-Vorlage ist meiner Meinung nach ein schöner Gewinn.
Es ist leicht, an Mikrodesign-Entscheidungen für :has() zu denken – wie eine Karte, wenn sie ein Bild enthält – aber ich denke, es wird auch für diese Makro-Layout-Änderungen wirklich nützlich sein.
Besseres Spezifitätsmanagement
Wenn Sie meinen vorherigen Artikel gelesen haben, wissen Sie, dass ich ein Liebhaber der Spezifität bin. Wenn Sie, wie ich, nicht möchten, dass Ihre Spezifitätswerte explodieren, wenn Sie :has() und :not() in Ihren Stilen verwenden, stellen Sie sicher, dass Sie :where() verwenden.
Das liegt daran, dass die Spezifität von :has() auf dem spezifischsten Element in seiner Argumentliste basiert. Wenn Sie also etwas wie eine ID darin haben (warum, bin ich mir nicht sicher!), wird Ihr Selektor in der Kaskade schwer zu überschreiben sein.
Auf der anderen Seite ist die Spezifität von :where() immer Null und erhöht niemals den Spezifitätswert.
/* specificity score: 0,1,0.
Same as a .standard-page--with-sidebar
modifier class
*/
.standard-page:where(:has(.sidebar)) {
/* etc */
}
Die Zukunft ist hell
Dies sind nur einige Dinge, die ich kaum erwarten kann, in der Produktion nutzen zu können. Der CSS-Tricks-Almanach enthält auch viele Beispiele. Was möchten Sie mit :has() machen? Was für reale Beispiele sind Ihnen begegnet, bei denen :has() die perfekte Lösung gewesen wäre?
Ich arbeite an der Vorlagenentwicklung und ich denke, das wäre das Beste, was ich in meinem Vorlagen-CSS verwenden sollte ✌️
Ja! Das sind gute Neuigkeiten.
Stellen Sie einfach sicher, dass Sie mit der Browserunterstützung zufrieden sind, wenn Sie mit der Verwendung beginnen. Firefox ist der wichtigste Browser, auf den die meisten Leute warten, aber selbst wenn Firefox ihn heute einführen würde und alle Firefox-Benutzer sofort aktualisieren würden, wären das immer noch < 85 % Unterstützung weltweit, wenn ich das richtig interpretiere: https://caniuse.com/css-has
Das liegt hauptsächlich an älteren Safari-Versionen, die noch in Gebrauch sind, sowie an Samsung Internet (vorerst).
Ausgezeichneter Beitrag und Informationen.
Ich liebe diesen nth-child-Trick für die Zebra-Streifen.
Vielen Dank, dass Sie mein Video erwähnt haben, Liam! Ich habe mich wirklich sehr gefreut.
Außerdem sind das wirklich schöne Beispiele.