Bisher waren für die Anwendung verschiedener Layouts auf eine Komponente basierend auf ihrem Inhalt entweder JavaScript oder bedingte Logik in Ihrer HTML-Vorlagensprache erforderlich, um Modifikatorklassen (wie .card--has-image oder .card--text-only) einzufügen.
Die Pseudoklasse :has() macht dies überflüssig, da sie als übergeordneter Selektor fungiert. Damit können Sie ein Container-Element abhängig davon, ob bestimmte untergeordnete Elemente vorhanden sind oder nicht, bedingt formatieren.
Mit :has() können Sie ganz einfach verschiedene Layoutvarianten in CSS definieren, die auf dem tatsächlichen DOM-Inhalt einer Komponente basieren. Sie können es optional auch mit :not() kombinieren, um explizit auf das Fehlen von Inhalten abzuzielen und Standardlayouts zu definieren.
Inhaltsbasiertes Container-Styling implementieren
ERFORDERLICH: Sie müssen den Selektor :has() für das Containerelement verwenden, um das Vorhandensein bestimmter untergeordneter Inhalte zu erkennen.
So erstellen Sie eine Komponente, deren Layout sich je nach Inhalt ändert:
- Standardstil definieren: Wenden Sie die grundlegenden Layoutstile auf das Container-Element an (z.B. ein einfacher einspaltiger Stapel).
- Inhaltsbasierte Überschreibungen anwenden: Richten Sie den Container mit
:has([child-selector])aus und wenden Sie die neuen Layoutstile für den Fall an, dass dieser Inhalt vorhanden ist (z.B. ein mehrspaltiges Raster).
Beispiel: Eine Kartenkomponente, die zu einem nebeneinander angeordneten Layout wechselt, wenn ein Bild vorhanden ist.
/* 1. Define the default state on the component container */
/* This applies when there is NO image */
.article-card {
display: flex;
flex-direction: column;
gap: 1rem;
padding: 1.5rem;
border: 1px solid #ccc;
border-radius: 8px;
}
/* 2. Apply styles when a specific child element is present */
/* MANDATORY: Target the container and use :has() to check for the descendant */
.article-card:has(img) {
/* Change the layout to a row if an image exists */
flex-direction: row;
align-items: center;
}
/* Optional: Style the image itself (no :has() needed here) */
.article-card img {
width: 150px;
height: auto;
border-radius: 4px;
}
/* You can also combine :has() and :not() to explicitly target the ABSENCE of content */
/* This selects a card that DOES NOT have an image */
.article-card:not(:has(img)) {
/* E.g., apply a different background color for text-only cards */
background-color: #f9f9f9;
}
<!-- Assume an <h1> precedes these components in the document layout -->
<!-- A card WITH an image (will use row layout) -->
<article class="article-card">
<img src="thumbnail.jpg" alt="Article thumbnail" />
<div class="content">
<h2>Card With Image</h2>
<p>This card lays out its content horizontally.</p>
</div>
</article>
<!-- A card WITHOUT an image (will use default column layout) -->
<article class="article-card">
<div class="content">
<h2>Text-Only Card</h2>
<p>This card lays out its content vertically, and gets its background color from the :not(:has()) rule.</p>
</div>
</article>
Leistungstipp: Wenn Sie :has() verwenden, sollten Sie den Selektor auf den spezifischsten Komponentencontainer (z. B. .article-card) beschränken. Vermeiden Sie es, ihn an sehr übergeordnete Elemente wie body:has(img) zu binden, wenn die Stiländerungen sehr lokal sind, da breite :has()-Abfragen zu mehr Neuberechnungen des Layouts führen können.
Fallback-Strategien
Wenn das inhaltsbasierte Layout-Styling für die Nutzerfreundlichkeit oder das Seitendesign entscheidend ist, musst du einen Fallback für Browser bereitstellen, die den :has()-Selektor nicht unterstützen. Für rein dekorative Effekte kann :has() als progressive Verbesserung ohne Fallback verwendet werden.
OBLIGATORISCH: Wenn Sie einen Fallback für kritische Layouts implementieren, müssen Sie in Ihrem CSS @supports not selector(:has(*)) verwenden, um einen herkömmlichen klassenbasierten Fallback zu definieren (z.B. .has-image).
Im Gegensatz zu interaktiven, zustandsbasierten Stilen ist das Vorhandensein von Inhalten in der Regel zum Zeitpunkt des Renderns bekannt. Die robusteste Fallback-Lösung besteht darin, dass die serverseitige Vorlagen-Engine (oder der Generator für statische Websites) eine Klasse wie .has-image in den Container einfügt, wenn das untergeordnete Element (z. B. ein Bild) in den Daten vorhanden ist.
Wenn serverseitiges Rendering nicht möglich ist, müssen Sie ein kleines Skript mit CSS.supports() verwenden, um den Inhalt zu erkennen und die Klasse beim Laden oder nach dem Einfügen dynamischer Inhalte anzuhängen.
/* Fallback CSS for older browsers */
/* We check if the browser DOES NOT support the :has() selector */
@supports not selector(:has(*)) {
/* Define a traditional modifier class that applies the exact same layout overrides */
.article-card.has-image {
flex-direction: row;
align-items: center;
}
.article-card:not(.has-image) {
background-color: #f9f9f9;
}
}
/* Fallback JavaScript for older browsers (if not using SSR to add the class) */
/* Check for support before running the script to avoid unnecessary work in modern browsers */
if (!CSS.supports('selector(:has(*))')) {
// Find all components that need checking
const cards = document.querySelectorAll('.article-card');
cards.forEach(card => {
// If the critical content exists, manually add the fallback class
if (card.querySelector('img')) {
card.classList.add('has-image');
}
});
}