Skip to content

Türchen 9 – Container Queries

Published: at 07:00 AM

Container Queries sind ein Wendepunkt im Responsive Design. Über ein Jahrzehnt lang mussten wir Komponenten basierend auf der Fensterbreite anpassen und das selbst dann, wenn die Komponente gar nicht die volle Breite einnahm. Das führte zu unflexiblen, kontextabhängigen Layouts und zu zahlreichen Workarounds.

Mit Container Queries werden Komponenten endlich kontextbewusst. Sie reagieren nicht auf den Viewport, sondern auf ihren eigenen Container. Das verändert Architekturentscheidungen, Designsysteme und die gesamte Denkweise im Frontend.

Warum Container Queries so wichtig sind

Das traditionelle responsive CSS basierte ausschließlich auf Media Queries, die den Viewport abfragen:

@media (min-width: 600px) {
  /* ... */
}

Dieses Modell hat ein fundamentales Problem. Es sagt nichts darüber aus, wie groß eine Komponente tatsächlich im Layout ist. Stell dir vor, eine Card liegt in einem zweispaltigen Grid. Der Viewport ist zwar 1200 Pixel breit, also weit im Desktop-Bereich, aber die Card selbst hat nur 400 Pixel Platz zur Verfügung. Die Media Query würde trotzdem Desktop-Styles aktivieren, was zu völlig unpassenden Layouts führt.

Die Konsequenzen dieses Mismatches sind gravierend. Die Typografie wird zu groß für den verfügbaren Raum und bricht in mehrere Zeilen um. Das Layout wirkt gequetscht und bricht unschön. Variantendesigns, die auf größere Breiten ausgelegt sind, funktionieren nicht sauber. Man musste bisher mit komplexen Klassennamen, JavaScript-basierten Lösungen oder zahlreichen Kompromissen arbeiten.

Mit Container Queries ändert sich das Spiel

Container Queries bieten eine elegante Lösung für dieses Jahrzehnte alte Problem:

@container (min-width: 400px) {
  /* Card kann sich nun anpassen */
}

Das Verhalten der Komponente orientiert sich jetzt am verfügbaren Platz innerhalb ihres Containers, nicht an der Fenstergröße des Browsers. Eine Card, die in einer schmalen Sidebar liegt, kann sich völlig anders verhalten als dieselbe Card im Hauptinhalt, selbst wenn beide auf demselben breiten Desktop-Monitor angezeigt werden. Die Komponente wird kontextbewusst und kann intelligent auf ihre tatsächliche Umgebung reagieren.

Container Queries aktivieren: container-type

Damit Container Queries funktionieren, muss ein Element explizit als Container definiert werden. Das geschieht über die CSS-Eigenschaft container-type:

.card {
  container-type: inline-size;
}

Die Eigenschaft container-type kann verschiedene Werte annehmen, wobei inline-size der mit Abstand häufigste ist. inline-size bedeutet, dass Container Queries auf Basis der Breite des Elements arbeiten (in horizontalen Schreibrichtungen wie Deutsch oder Englisch). Es gibt auch den Wert size, der sowohl Breite als auch Höhe für Queries verfügbar macht, aber das ist in der Praxis deutlich seltener sinnvoll, da Höhen oft dynamisch durch den Inhalt bestimmt werden.

Durch das Setzen von container-type: inline-size wird .card zum Container für seine eigenen Kinder. Das bedeutet, dass alle Nachfahren-Elemente innerhalb dieser Card nun mit @container-Regeln auf die Breite der Card reagieren können. Der Container bildet einen neuen Kontext für responsive Styles, der völlig unabhängig vom Viewport funktioniert.

Ein einfaches, aber mächtiges Beispiel

HTML

<div class="card">
  <div class="card__content">
    <h2>Title</h2>
    <p>Some content…</p>
  </div>
</div>

CSS

.card {
  container-type: inline-size;
  padding: 1rem;
  border: 1px solid #ccc;
}

@container (min-width: 500px) {
  .card__content {
    display: flex;
    gap: 1.5rem;
  }

  .card__content h2 {
    font-size: 1.75rem;
  }
}

Wenn die Card mindestens 500 Pixel breit wird, wechselt ihr Inhalt automatisch in ein zweispaltiges Layout mit Flexbox. Die Überschrift erhält gleichzeitig eine größere Schriftgröße. Der entscheidende Punkt dabei ist: Dieses Verhalten tritt unabhängig vom Viewport ein. Es spielt keine Rolle, ob das Browser-Fenster 800, 1200 oder 2000 Pixel breit ist. Allein die tatsächliche Breite der Card bestimmt ihr Aussehen.

Das ist ein fundamentaler Unterschied zu Media Queries. Eine Card in einer schmalen Sidebar würde vertikal bleiben, während dieselbe Card im breiten Hauptinhalt horizontal dargestellt wird. Die Komponente passt sich intelligent an ihren Kontext an, ohne dass man dutzende Varianten-Klassen oder komplexe JavaScript-Logik benötigt.

Container Names – mehrere Container in einem Element

In komplexeren Layouts braucht man oft mehrere Container-Kontexte, die unabhängig voneinander abgefragt werden können. Hier kommen Container Names ins Spiel:

.section {
  container-type: inline-size;
  container-name: section;
}

Durch die Vergabe eines Namens mit container-name kann man diesen spezifischen Container gezielt ansprechen:

@container section (min-width: 800px) {
  /* Layout für große Sektionen */
}

Das ist besonders wertvoll bei verschachtelten Containern. Stell dir vor, du hast eine große Section, die wiederum mehrere Cards enthält und beide sollen als Container fungieren. Ohne Names würde eine @container-Query immer den nächstgelegenen Container-Vorfahren ansprechen. Mit Namen kannst du explizit definieren, auf welchen Container sich eine Query beziehen soll.

Diese Fähigkeit ermöglicht sehr komplexe und flexible Komponentenarchitekturen. Du kannst Komponenten bauen, die gleichzeitig auf ihren eigenen Container und auf übergeordnete Container-Kontexte reagieren. Das eröffnet Möglichkeiten für responsive Design, die mit Media Queries schlichtweg nicht erreichbar waren.

Praxisbeispiel 1: Card-Komponente in mehreren Layoutvarianten

Ein klassischer Anwendungsfall für Container Queries ist eine Card-Komponente, die in verschiedenen Layouts unterschiedlich dargestellt werden soll. Die Anforderung ist simpel aber anspruchsvoll. Bei schmalen Breiten soll die Card vertikal aufgebaut sein, mit Bild oben und Text darunter. Bei größeren Breiten soll sie horizontal werden, mit dem Bild links und dem Text rechts daneben.

.card {
  container-type: inline-size;
}

@container (min-width: 450px) {
  .card {
    display: grid;
    grid-template-columns: 150px 1fr;
    gap: 1.25rem;
  }
}

Die Magie dabei ist die automatische Anpassung an den Kontext. Wenn diese Card in einem dreispaltigen Grid platziert wird, ist sie zu schmal für das horizontale Layout und bleibt vertikal. Dieselbe Card in einem zweispaltigen Grid hat mehr Platz und wechselt automatisch zur horizontalen Darstellung. Platziert man sie im Hauptinhalt über die volle Breite, wird sie ebenfalls horizontal.

Das Bemerkenswerte: Man braucht keine Media Queries, keine unterschiedlichen CSS-Klassen wie .card--horizontal oder .card--vertical, und kein JavaScript, das die Breite misst und Klassen dynamisch setzt. Die Komponente reguliert sich selbst, basierend auf ihrem verfügbaren Raum. Das ist echte Komponentenautonomie.

Praxisbeispiel 2: Navigation, die sich selbst reorganisiert

Navigation ist ein weiterer Bereich, in dem Container Queries ihre Stärken ausspielen. Traditionell musste man Navigationen mit Media Queries steuern:

@media (min-width: 800px) {
  nav ul {
    display: flex;
  }
}

Das Problem: Die Navigation reagiert auf die Fensterbreite, nicht auf ihren eigenen verfügbaren Raum. Wenn die Navigation in einer Sidebar liegt, die nur 300 Pixel breit ist, würde sie trotzdem versuchen, horizontal zu werden, sobald das Fenster breit genug ist. Das Ergebnis wäre ein gequetschtes, unlesbares Menü.

Mit Container Queries löst man dieses Problem elegant:

nav {
  container-type: inline-size;
}

@container (min-width: 500px) {
  nav ul {
    display: flex;
    gap: 1rem;
  }
}

Die Navigation reagiert jetzt auf die Breite ihrer eigenen Box, nicht auf die Fensterbreite. Das macht sie zu einer wirklich wiederverwendbaren Komponente. Dieselbe Navigation kann in der Hauptnavigation oben horizontal sein, in einer Sidebar vertikal bleiben und in einem Footer je nach verfügbarem Platz adaptieren.

Diese Flexibilität ist besonders wertvoll in verschiedenen Szenarien. Sidebars mit dynamischen Breiten profitieren enorm, weil die Navigation immer passend bleibt. Footer-Navigationen können sich anpassen, ohne spezielle Styles zu benötigen. In komponentenbasierten Architekturen wie React oder Vue bedeutet das, dass die Navigationskomponente wirklich portabel ist. Und in Microfrontend-Umgebungen, wo man oft keine Kontrolle über den umgebenden Layout-Kontext hat, wird die Navigation trotzdem korrekt dargestellt.

Praxisbeispiel 3: Responsive Formulare ohne Hacks

Formulare mit responsivem Layout waren schon immer eine Herausforderung. Man möchte, dass Formularfelder nebeneinander stehen, wenn genug Platz vorhanden ist, aber untereinander, wenn der Raum begrenzt ist. Mit Container Queries wird dieses Pattern elegant und wartbar:

.form {
  container-type: inline-size;
  display: grid;
  gap: 1rem;
}

@container (min-width: 600px) {
  .form {
    grid-template-columns: 1fr 1fr;
  }

  .full {
    grid-column: 1 / -1;
  }
}

Die gesamte Logik für das responsive Verhalten ist nun komponentenintern und vollkommen unabhängig von der Seitenstruktur. Das Formular kann in einem schmalen Modal eingespaltig bleiben, während dasselbe Formular auf einer breiten Seite zweispaltig wird. Man braucht keine speziellen Varianten-Klassen wie .form--narrow oder .form--wide, die man je nach Kontext manuell setzen müsste.

Besonders wertvoll ist diese Herangehensweise in Design-Systemen und Komponentenbibliotheken. Die Formularkomponente verhält sich überall gleich vorhersehbar, unabhängig davon, ob sie in einem Dashboard, in einer Checkout-Strecke oder in einem CMS-Backend eingesetzt wird. Die Komponente kennt ihre eigenen Bedürfnisse und reguliert sich selbst.

Container Queries + Component Libraries = perfekte Kombination

Container Queries passen perfekt zur modernen Komponentenarchitektur. In Designsystemen wie Storybook oder Figma kann man Komponenten isoliert entwickeln und dokumentieren, ohne sich Gedanken über den späteren Layout-Kontext machen zu müssen. Die Komponenten demonstrieren ihr responsives Verhalten direkt in Storybook, indem man einfach die Breite des Preview-Panels ändert.

Für Komponentenbibliotheken in React, Vue oder als Web Components bedeuten Container Queries echte Portabilität. Eine Card-Komponente verhält sich in jeder Anwendung gleich, egal ob sie in einem engen Sidebar-Kontext oder im Hauptinhalt eingesetzt wird. Das eliminiert einen Großteil der kontextabhängigen Props wie variant="compact" oder layout="horizontal", die man sonst von außen setzen müsste.

Atomic Design profitiert enorm von Container Queries. Moleküle und Organismen können echte Autonomie entwickeln. Sie müssen nicht mehr vom umgebenden Template wissen, wie sie sich verhalten sollen. Sie adaptieren sich selbst an ihren verfügbaren Raum. Das macht die Hierarchien klarer und die Komponenten wiederverwendbarer.

In Microfrontend-Architekturen, wo verschiedene Teams an unterschiedlichen Teilen einer Anwendung arbeiten, lösen Container Queries ein fundamentales Problem. Ein Team kann eine Komponente entwickeln, ohne genau zu wissen, in welchem Layout-Kontext andere Teams sie einsetzen werden. Die Komponente verhält sich überall gleich und korrekt, weil sie auf ihren eigenen Container reagiert, nicht auf globale Viewport-Eigenschaften.

Wann Container Queries besonders wertvoll sind

Container Queries entfalten ihren größten Nutzen in bestimmten Szenarien, die mit klassischen Media Queries nur schwer oder gar nicht lösbar waren.

Komponenten in verschiedenen Kontexten

Der offensichtlichste Anwendungsfall sind Komponenten, die an verschiedenen Stellen einer Anwendung eingesetzt werden. Eine Card kann in einem Grid, in einem Flexbox-Layout, in einem Carousel oder in einem Column-Layout erscheinen. Ohne Container Queries müsste man für jeden Kontext entweder spezielle Varianten-Klassen pflegen oder komplexe Media-Query-Kombinationen schreiben, die versuchen, den Kontext zu erraten. Mit Container Queries passt sich die Card einfach an ihren verfügbaren Raum an.

Dynamische Sidebars

Seiten mit Sidebars, die sich öffnen und schließen lassen, waren schon immer problematisch. Wenn sich eine Sidebar öffnet, verändert sich die verfügbare Breite für den Hauptinhalt dramatisch. Mit Media Queries konnte man darauf nicht reagieren, weil der Viewport sich ja nicht ändert. Man musste entweder mit JavaScript die Komponenten benachrichtigen oder mit komplexen Klassennamen-Manipulationen arbeiten. Container Queries lösen das Problem elegant. Der Hauptinhalt ist ein Container und alle Komponenten darin reagieren automatisch auf die neue Breite, wenn die Sidebar auf- oder zuklappt.

White-Labeling und Multi-Brand-UIs

Anwendungen, die für verschiedene Marken oder Kunden angepasst werden, haben oft sehr unterschiedliche Layout-Anforderungen. Kunde A bevorzugt eine breite Sidebar, Kunde B eine schmale. Mit Container Queries können dieselben Komponenten in beiden Layouts perfekt funktionieren, ohne dass man für jeden Kunden separate Komponenten-Varianten pflegen muss. Die Komponenten adaptieren sich an die jeweilige Layout-Philosophie.

Content-Management-Systeme

Wenn Komponenten in CMS-Umgebungen landen, hat man als Entwickler oft wenig Kontrolle über die finale Layout-Umgebung. Redakteure können Komponenten in verschiedensten Kontexten platzieren. Eine Bildergalerie könnte in der vollen Breite erscheinen, in einer zweispaltigen Ansicht oder in einem schmalen Sidebar-Widget. Container Queries stellen sicher, dass die Komponente überall korrekt dargestellt wird, ohne dass Redakteure technische Layout-Entscheidungen treffen müssen.

Microfrontend-Architekturen

In Microfrontend-Setups, wo verschiedene Teams an autonomen Teilen einer Anwendung arbeiten, sind die Layout-Kontexte oft komplett unterschiedlich. Team A entwickelt eine Produktliste, Team B integriert sie in ihr Dashboard. Ohne Container Queries müsste Team A entweder sehr defensiv programmieren und alle möglichen Breakpoints abdecken, oder Team B müsste die Komponente anpassen. Mit Container Queries funktioniert die Komponente einfach, weil sie auf ihren eigenen Raum reagiert, nicht auf globale Viewport-Eigenschaften.

Ein weiteres Beispiel aus einem Projekt

Ein konkretes Beispiel aus einem realen Projekt verdeutlicht den Unterschied zwischen Media Queries und Container Queries eindrucksvoll. Ein Kunde betrieb eine E-Commerce-Plattform mit komplexen Produktlistungs-Layouts. Die Anforderung war klassisch. Auf schmalen Mobile-Screens sollten die Product Cards einspaltig dargestellt werden. Auf Tablets zweispaltig. Auf Desktop-Bildschirmen drei oder vier Spalten, je nach verfügbarer Breite.

Der alte Ansatz mit Media Queries

Die ursprüngliche Lösung mit Media Queries wurde schnell zum Wartungsalbtraum. Das Team musste hunderte von Overrides pflegen, weil die Cards in verschiedenen Seitenabschnitten unterschiedlich breit waren. Es gab über fünf verschiedene Breakpoints, die alle leicht unterschiedliche Werte hatten, weil verschiedene Entwickler zu verschiedenen Zeiten an verschiedenen Teilen der Seite gearbeitet hatten.

Das größte Problem war aber das ständige “Breite wackelt ein bisschen”. Wenn der Browser genau an einem Breakpoint war, konnten minimale Änderungen, wie ein zusätzliches Padding hier, ein dickerer Border dort, dazu führen, dass das Layout plötzlich gequetscht aussah. Das Team verbrachte Stunden damit, pixelgenaue Breakpoints zu justieren, nur um festzustellen, dass sie beim nächsten Feature wieder angepasst werden mussten.

Die Lösung waren Container Queries

Die Umstellung auf Container Queries vereinfachte die gesamte Architektur dramatisch:

.product-card {
  container-type: inline-size;
}

@container (min-width: 400px) {
  .product-card {
    grid-template-columns: 150px 1fr;
  }
}

@container (min-width: 700px) {
  .product-card {
    grid-template-columns: 200px 1fr;
  }
}

Plötzlich brauchte man nur noch zwei Container Queries pro Card-Komponente. Keine seitenspezifischen Overrides mehr. Keine unterschiedlichen Breakpoints je nach Kontext. Die Card wusste selbst, wie sie sich verhalten sollte, basierend auf ihrem verfügbaren Raum.

Das gesamte System wurde dadurch stabiler, weil die Komponenten nicht mehr von globalen Viewport-Werten abhingen. Es wurde modularer, weil man Cards in neuen Kontexten einsetzen konnte, ohne zusätzliches CSS schreiben zu müssen. Es wurde deutlich einfacher zu pflegen, weil die responsive Logik direkt bei der Komponente lag, nicht über dutzende CSS-Dateien verstreut war. Die Entwicklungsgeschwindigkeit erhöhte sich merklich, und die Anzahl der Layout-Bugs ging drastisch zurück.

Fazit

Container Queries verändern fundamental, wie wir über responsives Design nachdenken. Sie verschieben die Verantwortlichkeit von der Seite zur Komponente. Statt dass das Seitenlayout bestimmt, wie sich eine Komponente verhält, entscheidet die Komponente selbst, basierend auf ihrem verfügbaren Raum.

Diese Verschiebung hat weitreichende Konsequenzen für die Architektur moderner Webanwendungen. Man braucht deutlich weniger Media Queries, weil viele responsive Entscheidungen jetzt auf Komponentenebene getroffen werden. Die Systeme werden modularer, weil Komponenten nicht mehr vom globalen Layout-Kontext abhängen. Die Komponenten selbst werden robuster, weil sie in verschiedenen Kontexten konsistent funktionieren. Die Verantwortlichkeiten werden klarer, weil jede Komponente ihr eigenes responsives Verhalten kapselt. Und die Wiederverwendbarkeit steigt dramatisch, weil Komponenten wirklich portabel werden.

Container Queries sind nicht einfach nur ein weiteres CSS-Feature, das man in sein Werkzeug-Arsenal aufnimmt. Sie markieren einen echten Paradigmenwechsel. Sie ermöglichen eine Art von komponentenbasierter Entwicklung, die bisher nur mit erheblichem Mehraufwand oder gar nicht möglich war. Nach Jahren des Wartens auf diese Funktionalität haben Browser sie endlich implementiert, und es ist Zeit, dass wir als Frontend-Community unsere Arbeitsweise entsprechend anpassen. Die Zukunft des responsiven Designs ist containerbasiert und nicht viewportbasiert.


☕ Buy me a coffee

Wenn Dir meine Beiträge gefallen und sie Dir bei Deiner Arbeit helfen, würde ich mich über einen "Kaffee" und ein paar nette Worte von Dir freuen.

Buy me a coffee

Previous Post
Türchen 10 – Modern Responsive Design
Next Post
Türchen 8 – Grid Advanced Features

Kommentare