Komponenten statt Viewport
CSS Container Queries beenden das Zeitalter der viewport-zentrierten Responsiveness. Eine Karte weiß jetzt, wie breit ihr Container ist — und passt sich an, egal ob sie in einer Sidebar, einem Hauptbereich oder einem Modal erscheint. Das verändert die CSS-Architektur von Grund auf.
Inhaltsverzeichnis
- 1. Das Viewport-Problem: Warum Media Queries zu kurz greifen
- 2. container-type: einen Containment-Kontext deklarieren
- 3. container-name: benannte Container für präzise Abfragen
- 4. @container-Regeln schreiben
- 5. Container Query Einheiten: cqi, cqw, cqb, cqh
- 6. Style Queries: auf Custom Properties reagieren
- 7. Architektur: Container Queries und komponentenbasiertes CSS
- 8. Container Queries vs. Media Queries im Vergleich
- 9. Fallstricke und häufige Fehler
- 10. Zusammenfassung
- 11. FAQ
1. Das Viewport-Problem: Warum Media Queries zu kurz greifen
Media Queries basieren auf der Viewport-Breite — der gesamten Breite des Browser-Fensters. Das war sinnvoll, als Webseiten aus einem einzigen, linearen Fließbereich bestanden. Moderne Web-Anwendungen sind aber komponentenbasiert: Dieselbe Karten-Komponente erscheint im Hauptbereich (700px breit), in einer Sidebar (280px breit), in einem Modal (400px breit) und in einem Grid mit vier Spalten (jeweils 200px breit) — alles auf demselben Viewport mit 1440px Breite. Media Queries können diesen Kontext nicht unterscheiden.
Das klassische Lösungsmuster war, für jeden Verwendungskontext spezifische CSS-Klassen zu schreiben: .card, .sidebar .card, .modal .card. Das führt zu Codeduplizierung, Kontext-Abhängigkeiten und einem Stylesheet, in dem Komponentenstile über das gesamte Dokument verteilt sind. CSS Container Queries lösen dieses Problem strukturell: Eine Komponente definiert ihre eigenen Responsive-Breakpoints relativ zum Container, in dem sie liegt — nicht relativ zum Viewport. Dieselbe Karte passt sich überall korrekt an, ohne kontextspezifische Überschreibungen.
Der konzeptuelle Sprung bei CSS Container Queries: Responsiveness ist eine Eigenschaft der Komponente, nicht des Layouts. Eine gut designte Komponente mit CSS Container Queries kann in jeden Container platziert werden und sieht dort korrekt aus — sie ist wirklich selbstständig. Das ist das Prinzip, das React, Vue und Web Components auf der Logik-Ebene schon längst umsetzen, auf der CSS-Ebene aber bisher fehlte.
2. container-type: einen Containment-Kontext deklarieren
Um CSS Container Queries auf einem Element zu ermöglichen, muss dessen Elternelement als Container deklariert werden. Das geschieht mit der container-type-Eigenschaft. Der Wert inline-size erstellt einen Containment-Kontext für die inline-Achse (in horizontalen Schreibsystemen: die Breite). Das ist der häufigste Anwendungsfall: Kinder-Elemente fragen die Breite ihres Containers ab. Der Wert size erstellt einen Containment-Kontext für beide Achsen (Breite und Höhe), ist aber restriktiver und erfordert, dass die Höhe des Containers bekannt ist.
Ein wichtiger technischer Hintergrund: container-type: inline-size aktiviert CSS Containment für die Größenberechnung der inline-Achse. Das bedeutet, der Container kann nicht mehr von seinen Kinderinhalten in der inline-Richtung beeinflusst werden — er muss selbst eine definierte Größe haben oder von seinem Elternelement eine erhalten. Das ist die Voraussetzung dafür, dass CSS Container Queries die Containergröße zuverlässig abfragen können, ohne in eine Zirkularabhängigkeit zu geraten.
Wer container-type versehentlich auf das falsche Element setzt, erhält keine Fehlermeldung, aber die CSS Container Queries funktionieren nicht wie erwartet. Häufiger Fehler: container-type auf die Komponente selbst statt auf deren Elternelement setzen. Die Komponente kann ihren eigenen Container nicht abfragen — CSS Container Queries fragen immer den nächsten Vorfahren mit einem Containment-Kontext ab, der ein Vorgänger-Element ist, nie das Element selbst.
/* Setting up container contexts for CSS Container Queries */
/* Parent element declares containment — NOT the component itself */
.card-grid {
container-type: inline-size;
container-name: card-grid; /* optional: named for precision */
}
/* Component styles adapt based on its container's width */
.card {
display: flex;
flex-direction: column;
padding: 1rem;
gap: 0.75rem;
}
/* Container Query: when card-grid is >= 480px wide */
@container card-grid (min-width: 480px) {
.card {
flex-direction: row;
align-items: center;
}
.card__image { width: 160px; flex-shrink: 0; }
}
/* Container Query: even wider layout */
@container card-grid (min-width: 720px) {
.card {
padding: 1.5rem;
gap: 1.25rem;
}
}
/* Multiple containers in the same document */
.sidebar {
container-type: inline-size;
container-name: sidebar;
}
/* The same .card component adapts to sidebar context */
@container sidebar (max-width: 320px) {
.card { flex-direction: column; }
.card__image { width: 100%; }
}
3. container-name: benannte Container für präzise Abfragen
Mit container-name kann ein Container einen Namen erhalten, der in CSS Container Queries verwendet werden kann, um gezielt auf diesen Container zu referenzieren. Ohne Name sucht @container nach dem nächsten Vorfahren mit einem Containment-Kontext — mit Name nach dem nächsten Vorfahren mit diesem spezifischen Namen. Das ist entscheidend, wenn verschachtelte Container existieren und eine tief liegende Komponente auf einen weiter entfernten Container reagieren soll.
Benannte Container ermöglichen außerdem klare, selbstdokumentierende CSS Container Queries-Regeln. @container card-grid (min-width: 480px) kommuniziert sofort, dass diese Regel auf das Karten-Grid-Layout bezogen ist — nicht auf irgendeinen anonymen Container. In großen Projekten mit vielen verschachtelten Containern ist diese Explizitheit wichtig für die Wartbarkeit. Die Namenskonvention sollte zur Komponentenarchitektur passen und in einem Styleguide dokumentiert werden.
Ein fortgeschrittenes Muster mit benannten Containern: Ein Container kann gleichzeitig Containment-Kontext für mehrere Kinder-Komponenten sein, die unterschiedliche Breakpoints für denselben Container definieren. Eine Navigationskomponente, eine Inhaltskomponente und eine Footer-Komponente innerhalb desselben container-type: inline-size-Elternelements können alle auf dessen Breite reagieren — mit jeweils eigenen Breakpoints. Das ist präzises, komponentenbasiertes Responsive Design mit CSS Container Queries.
4. @container-Regeln schreiben
CSS Container Query-Regeln werden mit @container geschrieben und unterstützen dieselben Größenvergleiche wie Media Queries: min-width, max-width, min-height, max-height sowie die modernen Bereichsabfragen (width >= 480px, 480px <= width <= 720px). Innerhalb des @container-Blocks gelten normale CSS-Regeln — alle Eigenschaften, Selektoren und Werte sind verwendbar.
Bereichsabfragen in CSS Container Queries sind eleganter als das klassische min/max-Muster: @container (480px <= inline-size <= 720px) definiert einen exakten Bereich ohne die min-width/max-width-Redundanz. Das Schlüsselwort inline-size ist expliziter als width und kommuniziert, dass die logische Inline-Achse gemeint ist — in Sprachen mit vertikaler Schrift ist das nicht zwingend die horizontale Achse.
Verschachtelte CSS Container Queries sind möglich: Innerhalb eines @container-Blocks kann eine weitere @container-Regel stehen. Das ermöglicht komplexe responsive Logik, die sowohl auf einen äußeren als auch auf einen inneren Container reagiert. In der Praxis sollte man Verschachtelung sparsam einsetzen — zu tiefe Container-Hierarchien machen das CSS schwer zu debuggen und verlangsamen unter Umständen das Browser-Rendering.
/* CSS Container Queries — range syntax and named containers */
.product-list {
container-type: inline-size;
container-name: product-list;
}
/* Modern range syntax — more readable than min/max */
@container product-list (inline-size >= 600px) {
.product-card {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: auto;
}
}
@container product-list (inline-size >= 900px) {
.product-card {
grid-template-columns: 280px 1fr auto;
}
.product-card__actions {
display: flex;
flex-direction: column;
justify-content: center;
gap: 0.5rem;
}
}
/* Range: apply only in a specific width window */
@container product-list (600px <= inline-size <= 900px) {
.product-card__badge { display: none; } /* Too cramped for badge */
}
/* Nested containers for two-level responsive logic */
.page-layout {
container-type: inline-size;
container-name: page;
}
.sidebar {
container-type: inline-size;
container-name: sidebar;
}
/* Widget responds to sidebar width, not page width */
@container sidebar (inline-size < 240px) {
.widget-chart { display: none; }
.widget-summary { font-size: 0.75rem; }
}
5. Container Query Einheiten: cqi, cqw, cqb, cqh
CSS Container Query Einheiten sind relative Längeneinheiten, die sich auf die Dimensionen des nächsten Containment-Kontexts beziehen. cqw ist 1% der Containerbreite (container query width), cqh ist 1% der Containerhöhe. cqi ist 1% der Inline-Größe des Containers (in horizontalen Schreibsystemen identisch mit cqw), cqb ist 1% der Block-Größe. cqmin und cqmax sind das Minimum bzw. Maximum der beiden Achsen.
CSS Container Query Einheiten ermöglichen Fluid Typography auf Komponentenebene — analog zu vw für Fluid Typography auf Viewport-Ebene. Statt font-size: clamp(1rem, 3vw, 2rem) kann man font-size: clamp(1rem, 3cqi, 2rem) verwenden. Das bedeutet, die Schriftgröße skaliert mit der Breite des Containers statt des Viewports — ideal für Komponenten, die in verschiedenen Kontexten mit unterschiedlichen Breiten erscheinen. Ein Hero-Titel passt sich automatisch an, ob er im Full-Width-Bereich oder in einem 480px-Modal erscheint.
Der Unterschied zwischen cqw und cqi: Bei horizontalen Schreibsystemen (LTR, RTL) ist die Inline-Achse die horizontale, sodass cqi und cqw identisch sind. Bei vertikalen Schreibsystemen (japanisch, chinesisch traditionell) ist die Inline-Achse die vertikale, und cqi bezieht sich auf die Höhe. Für mehrsprachige Projekte ist cqi die logisch korrektere Einheit, da sie mit der Schreibrichtung skaliert.
6. Style Queries: auf Custom Properties reagieren
CSS Style Queries sind die zweite Form von Container Queries und ermöglichen es, auf Custom Property-Werte eines Containers zu reagieren. Während Größen-Container-Queries auf die Abmessungen reagieren, reagieren Style Queries auf deklarative Zustände. @container style(--card-variant: featured) gilt, wenn der Container die Custom Property --card-variant mit dem Wert featured hat. Das ist ein deklarativer Mechanismus für Komponentenvarianten — ohne JavaScript, ohne BEM-Klassen, ohne Data-Attribute.
CSS Style Queries verändern den Ansatz für Komponentenvarianten fundamental. Statt .card--featured, .card--compact und .card--hero als separate CSS-Klassen zu definieren, setzt man Custom Properties auf dem Container und lässt die Kind-Elemente per Style Queries darauf reagieren. Das hält Komponentenstile kohärent und macht Varianten deklarativ konfigurierbar. Ein Elternelement kann das Layout seiner Kind-Komponenten durch Custom Properties steuern, ohne die Klassen der Kinder zu kennen.
Browser-Support für CSS Style Queries: Chrome 111+, Safari 17.2+, Firefox 128+. Die Unterstützung ist breiter als für Größen-Container-Queries. Style Queries sind besonders mächtig in Kombination mit Design-Token-Custom-Properties: Eine Theme-Komponente setzt --theme: dark, und alle Kind-Komponenten passen sich mit Style Queries automatisch an — ohne Klassen-Propagierung durch den DOM.
/* CSS Style Queries — component variants via custom properties */
/* Parent declares containment (required for style queries too) */
.card-wrapper {
container-type: style; /* or inline-size for combined queries */
}
/* Variant 1: featured card */
.card-wrapper[data-variant="featured"] {
--card-variant: featured;
}
/* Child components react to parent's custom property */
@container style(--card-variant: featured) {
.card {
grid-column: span 2;
background: var(--color-brand-subtle);
}
.card__title { font-size: var(--text-2xl); }
.card__badge { display: block; }
}
/* Variant 2: compact */
@container style(--card-variant: compact) {
.card {
padding: 0.5rem;
gap: 0.25rem;
}
.card__image { display: none; }
.card__description { display: none; }
}
/* Combined: size AND style query */
@container product-list (inline-size >= 600px) and style(--card-variant: featured) {
.card {
grid-template-columns: 320px 1fr;
font-size: 1.125rem;
}
}
7. Architektur: Container Queries und komponentenbasiertes CSS
CSS Container Queries verändern die Art, wie man CSS-Dateien organisiert. In einer viewport-zentrierten Architektur liegt die Responsive-Logik oft in globalen Stylesheet-Abschnitten oder separierten @media-Blöcken am Ende der Datei. Mit CSS Container Queries gehört die Responsive-Logik in die Komponente selbst — direkt neben den Standard-Stilen der Komponente. Eine Karten-Komponente enthält ihre eigenen @container-Regeln, und die Datei ist vollständig selbstständig.
Die Implikation für Design-Systeme: Komponenten mit CSS Container Queries sind echte Black Boxes. Wer eine Karte in ein Grid einfügt, muss keine kontextspezifischen CSS-Überschreibungen schreiben. Die Karte kümmert sich selbst um ihr Layout. Das reduziert das Wissen, das Entwickler über andere Komponenten benötigen, und macht Design-Systeme robuster gegen unerwartete Layouts in neuen Kontexten.
Ein Architekturprinzip für CSS Container Queries: Container-Deklarationen (container-type, container-name) gehören zu Layout-Komponenten, nicht zu Inhaltskomponenten. Ein Grid-Wrapper, eine Sidebar, ein Modal — das sind Layout-Kontexte. Eine Karte, ein Button, ein Formularfeld — das sind Inhaltskomponenten, die auf Container reagieren. Diese Trennung macht die Architektur vorhersehbar: Inhaltskomponenten wissen, dass sie immer in einem deklarierten Container sitzen werden.
8. Container Queries vs. Media Queries im Vergleich
Beide Techniken lösen unterschiedliche Probleme. CSS Container Queries und Media Queries ergänzen sich — sie ersetzen sich nicht gegenseitig. Ein vollständig responsives Projekt verwendet beide Techniken für die jeweiligen Anwendungsfälle, in denen sie überlegen sind.
| Kriterium | Media Queries | Container Queries | Empfehlung |
|---|---|---|---|
| Kontext | Gesamt-Viewport | Eltern-Container | CQ für Komponenten |
| Komponenten-Wiederverwendung | Kontext-Abhängig | Vollständig portabel | CQ für Design-Systeme |
| Layout-Wechsel (global) | Ideal (Navigation, Spalten) | Nicht möglich (keine Viewport-Info) | MQ für globales Layout |
| Fluid Typography (Komponent) | Nur viewport-relativ (vw) | Container-relativ (cqi) | CQ + cqi für Komponenten |
| Browser-Support | Alle Browser seit Jahren | Chrome 105+, Safari 16+, FF 110+ | CQ für neue Projekte |
Die praktische Empfehlung: CSS Container Queries für alle Komponentenstile verwenden — Karten, Tabellen, Formulare, Widgets. Media Queries für globale Layout-Entscheidungen behalten — Anzahl der Spalten im Hauptgrid, Navigation mobile vs. desktop, Sidebar ein-/ausblenden. Diese Aufteilung spiegelt die natürliche Trennung zwischen Layout-Entscheidungen (global, viewport-abhängig) und Komponenten-Entscheidungen (lokal, container-abhängig) wider.
9. Fallstricke und häufige Fehler
Der häufigste Fehler bei CSS Container Queries: container-type auf die Komponente selbst statt auf deren Elternelement setzen. Eine Komponente kann nicht ihren eigenen Container abfragen — der Containment-Kontext wird immer vom Vorfahren ausgelesen. Wenn man container-type: inline-size auf eine .card setzt und dann @container (min-width: 400px) innerhalb der .card-Regeln verwendet, funktioniert die Abfrage nie korrekt, weil die Karte keine Kinder hat, die innerhalb des @container-Blocks definiert sind, oder weil der Containment-Kontext vom falschen Element ausgeht.
Ein zweiter Fallstrick: Intrinsic Sizing-Konflikte. Wenn ein Container container-type: inline-size hat, dürfen seine Kinder die Container-Breite nicht durch ihren Inhalt beeinflussen. Ein Container mit width: max-content und container-type: inline-size kombiniert schafft eine Zirkularabhängigkeit, die Browser unterschiedlich auflösen. Der Container braucht eine definierte Breite — entweder durch explizite Angabe, durch Block-Layoutregeln oder durch Elternconstraints.
Ein dritter häufiger Fehler ist das Vergessen von container-type in CSS-Reset-Schichten. Wenn ein CSS-Reset oder Normalize alle Eigenschaften zurücksetzt, kann container-type auf normal (den Defaultwert ohne Containment) zurückgesetzt werden. Das führt dazu, dass CSS Container Queries nicht mehr funktionieren. container-type sollte in CSS Cascade Layers in der richtigen Schicht deklariert werden, sodass der Reset die Deklaration nicht überschreibt.
/* CSS Container Queries — common mistakes and corrections */
/* WRONG: container-type on the component itself */
.card {
container-type: inline-size; /* card cannot query itself */
}
@container (min-width: 400px) {
.card__content { flex-direction: row; } /* Will not work as expected */
}
/* RIGHT: container-type on the parent wrapper */
.card-wrapper {
container-type: inline-size;
container-name: card-wrapper;
}
.card { /* No container-type here */ }
@container card-wrapper (min-width: 400px) {
.card__content { flex-direction: row; } /* Works correctly */
}
/* Container Query Units in component fluid typography */
.hero-card {
container-type: inline-size;
container-name: hero-card;
}
@layer components {
.hero-card__title {
/* Fluid size: relative to CONTAINER, not viewport */
font-size: clamp(1.25rem, 5cqi, 2.5rem);
line-height: clamp(1.2, 1.1 + 0.5cqi, 1.4);
}
}
/* Style Query — boolean-style check for a custom property */
@container style(--is-featured: true) {
.card { outline: 3px solid oklch(55% 0.25 290); }
.card__badge { display: block; }
}
Mironsoft
Komponentenbasierte CSS-Architektur und Hyvä-Theme-Entwicklung
CSS Container Queries in euer Design-System integrieren?
Wir migrieren viewport-zentrierte Komponenten zu Container Queries, definieren Container-Architekturen und bauen Style-Query-basierte Varianten-Systeme für Hyvä-Themes und Magento-Frontend-Projekte.
Container-Architektur
Container-Hierarchie und Namenskonventionen für euer Komponentensystem definieren
Komponent-Migration
Media-Query-basierte Komponenten auf Container Queries umstellen
Style Queries
Komponentenvarianten als Style Queries implementieren — ohne JavaScript-Klassenwechsel
10. Zusammenfassung
CSS Container Queries sind das fehlende Puzzlestück für echtes komponentenbasiertes Responsive Design. Mit container-type: inline-size auf dem Elternelement und @container-Regeln in der Komponente reagiert eine Karte auf die Breite ihres Containers — nicht auf den Viewport. Dieselbe Komponente funktioniert in einer Sidebar, einem Hauptbereich, einem Modal und einem Grid, ohne kontextspezifische Überschreibungen. Container Query Einheiten (cqi, cqw) ergänzen Fluid Typography auf Komponentenebene, und Style Queries ermöglichen deklarative Komponentenvarianten über Custom Properties.
Die wichtigsten Architekturentscheidungen: container-type auf Layout-Elemente setzen, nicht auf Inhaltskomponenten. Benannte Container für klare, wartbare CSS Container Queries-Regeln verwenden. Media Queries und CSS Container Queries kombinieren — globales Layout per Media Query, Komponentenanpassungen per Container Query. Style Queries für Varianten-Systeme einsetzen. Und cqi-Einheiten für Fluid Typography auf Komponentenebene verwenden, um dieselbe flüssige Skalierung zu erreichen wie vw auf Viewport-Ebene.
CSS Container Queries — Das Wichtigste auf einen Blick
Setup
container-type: inline-size auf das Elternelement. container-name für Präzision. Nie auf die Komponente selbst — sie kann sich nicht selbst abfragen.
@container-Regeln
Wie @media, aber relativ zum Container. Moderne Range-Syntax: @container (inline-size >= 480px). Benannt: @container card-grid (min-width: 480px).
CQ-Einheiten
cqi = 1% der Container-Inline-Größe. Für Fluid Typography in Komponenten: clamp(1rem, 5cqi, 2.5rem) skaliert mit Container, nicht Viewport.
Style Queries
@container style(--variant: featured) — reagiert auf Custom Properties. Deklarative Komponentenvarianten ohne JavaScript oder BEM-Modifier-Klassen.