Zwanzig Jahre lang stützte sich die Anpassung von Oberflächen auf eine einzige Bezugsgröße: die Breite des Browserfensters. Media Queries fragen den Viewport ab, nie den tatsächlich verfügbaren Platz um eine Komponente. Container Queries heben diese Grenze auf, indem ein Element auf die Größe seines Containers reagiert. Derselbe Block kann dann in einer Seitenleiste kompakt und in der Seitenmitte erweitert erscheinen, ohne von der Bildschirmauflösung abzuhängen.
Das Prinzip: den Container abfragen, nicht das Fenster
Der Mechanismus läuft in zwei Schritten. Ein Elternelement wird als Abfrage-Container deklariert; seine Nachfahren können ihr Layout dann an die Größe dieses Containers knüpfen. Die Deklaration erfolgt über die Eigenschaft container-type, bei Bedarf ergänzt um einen Namen via container-name.
.card-container {
container-type: inline-size;
container-name: card;
}
/* The card reacts to its container width, not the viewport */
@container card (min-width: 30rem) {
.card {
display: grid;
grid-template-columns: 12rem 1fr;
gap: 1.5rem;
}
}Der Wert inline-size weist den Browser an, die Inline-Dimension zu beobachten, also die Breite bei horizontaler Schrift, während die Höhe frei bleibt. Das ist die häufigste Einstellung, weil sie die Nebenwirkungen einer Eingrenzung auf beiden Achsen vermeidet. Wie das Anchor Positioning nehmen Container Queries eine Schicht JavaScript weg, die früher zum Vermessen von Elementen nötig war.
Die Container-Einheiten
Wo Media Queries viewport-relative Einheiten wie vw und vh hatten, führen Container Queries eigene ein, berechnet auf die Größe des nächsten Abfrage-Containers. Damit lassen sich Typografie und Abstände proportional zur Komponente dimensionieren.
| Einheit | Bezug | Viewport-Äquivalent |
|---|---|---|
cqw | 1 % der Container-Breite | vw |
cqh | 1 % der Container-Höhe | vh |
cqi | 1 % der Inline-Größe | vi |
cqb | 1 % der Block-Größe | vb |
cqmin | die kleinere der beiden | vmin |
cqmax | die größere der beiden | vmax |
.card h3 {
/* Fluid heading, indexed on the container width */
font-size: clamp(1rem, 4cqi, 1.75rem);
}Eine Komponente, zwei Kontexte
Der Nutzen zeigt sich an einer mehrfach verwendeten Komponente. Dieselbe Produktkarte, in ein dreispaltiges Raster oder ein Banner über die volle Breite gesetzt, nimmt zwei Layouts an, ohne eine einzige globale Media Query. Das Markup bleibt identisch; allein die Container-Breite entscheidet.
<div class="card-container">
<article class="card">
<img src="/product.jpg" alt="" />
<div class="body">
<h3>Product name</h3>
<p>Short description.</p>
</div>
</article>
</div>Media Queries und Container Queries: einander ergänzend
Container Queries ersetzen die Media Queries nicht, sie ergänzen sie. Die grobe Seitenstruktur, ihre Layout-Abstände und ihre großen Umbruchpunkte bleiben vom Viewport gesteuert, weil sie tatsächlich von Bildschirmgröße und Geräteausrichtung abhängen. Container Queries übernehmen im Inneren, auf der Ebene wiederverwendbarer Komponenten, wo die verfügbare Breite von Ort zu Ort schwankt. Beide Mechanismen leben in derselben Stylesheet, ohne sich zu stören: Es liegt am Autor, die Grenze zu ziehen und den Viewport dem Gesamtlayout, den Container dem Verhalten der Interface-Bausteine vorzubehalten.
Container benennen und verschachteln
Die Kurzschreibweise container vereint Typ und Namen in einer einzigen Deklaration. Container zu benennen wird schnell unverzichtbar, sobald sie sich verschachteln: eine namenlose Abfrage zielt auf den nächsten Vorfahren-Container, der nicht immer der erwartete ist. Mit einem expliziten Namen erreicht die Abfrage eindeutig die richtige Ebene, auch über mehrere verschachtelte Container hinweg. Diese Namensdisziplin entspricht der eines Komponentensystems: jeder wichtige Seitenbereich, Seitenleiste, Hauptinhalt oder Kartenfuß, profitiert von einem stabilen Namen, den die enthaltenen Komponenten wiederverwenden.
/* Shorthand: type and name in one declaration */
.sidebar { container: rail / inline-size; }
.main { container: content / inline-size; }
/* The query targets the nearest named container */
@container rail (max-width: 20rem) {
.widget { font-size: 0.875rem; }
}Schrittweiser Rollout
Die Funktion ist in den aktuellen Versionen der großen Browser verfügbar, doch eine reichweitenstarke Website behält stets einen Anteil an Besuchern auf älteren Versionen. Progressive Enhancement beantwortet diesen Fall: die Regel @supports aktiviert das bedingte Layout nur dort, wo container-type erkannt wird, und lässt anderswo eine gut lesbare Rückfalldarstellung. Die Komponente bleibt überall funktionsfähig, nur eben reicher, wo der Browser es zulässt. Dieser Ansatz vermeidet die klassische Alles-oder-nichts-Falle, in der eine neue Funktion die Darstellung auf älteren Konfigurationen zerlegt.
/* Progressive enhancement: only opt in when supported */
@supports (container-type: inline-size) {
.card-container { container-type: inline-size; }
}Typografie und umfließender Inhalt
Über die Anordnung hinaus verfeinern Container Queries die Typografie. In Kombination mit den cq*-Einheiten und der Funktion clamp() erzeugen sie Schriftgrößen, die der Komponentenbreite ohne harte Stufen folgen. Der Lesekomfort bleibt erhalten, wenn derselbe Block von einer schmalen Spalte zur vollen Breite wechselt. Ein Vorbehalt: eine Schriftgröße allein am Container auszurichten, kann die Barrierefreiheit beeinträchtigen, wenn die Skala die Vorlieben der Nutzer ignoriert. Bewährt ist es, die Werte mit clamp() zu begrenzen und eine Basis in relativen Einheiten zu behalten, damit Zoom und Systemeinstellungen weiterhin respektiert werden.
Was Container Queries nicht leisten
Ein Element kann sich nicht selbst abfragen: die Abfrage zielt immer auf einen Vorfahren-Container, nie auf das Element, das container-type deklariert. Die Eingrenzung hat zudem Renderkosten und bleibt besser den Komponenten vorbehalten, die davon profitieren, statt der Dokumentwurzel. Schließlich erweitern Style Queries das Prinzip auf die benutzerdefinierten Eigenschaften des Containers, nützlich neben Design Tokens.
/* Style query: react to a custom property on the container */
@container style(--density: compact) {
.card { padding: 0.5rem; }
}Eine Komponente ist nicht mehr auf Seitenebene responsive, sondern auf der Ebene ihres Platzes.
Vorsicht: container-type: size grenzt beide Achsen ein und verlangt eine explizite Höhe, sonst kann der Inhalt verschwinden. In den allermeisten Fällen ist inline-size die richtige Wahl.
Das Wesentliche
Container Queries verlagern die responsive Logik vom Dokument zur Komponente. Zusammen mit den cq*-Einheiten und, bald überall, den Style Queries machen sie Interface-Bibliotheken wirklich portabel von einem Kontext zum nächsten. Sie ergänzen eine Familie moderner CSS-Funktionen neben den View Transitions, die jeweils die Abhängigkeit von JavaScript verringern.
Lange habe ich Komponenten dupliziert, um ihre Varianten je nach Platzierung zu verwalten. Seit ich auf Container Queries setze, pflege ich eine einzige Komponente und lasse sie sich dort anpassen, wo sie steht: mein CSS ist schlanker geworden und meine Code Reviews auch. Es ist eine der seltenen Änderungen, die zugleich den Code und die Architektur vereinfacht. — Simon Janvier
Zum Weiterlesen
Referenzdokumentation: Container Queries auf MDN.
