Ein Baustein aus einer Bibliothek landet an vielen Stellen: einmal über die volle Breite, einmal als eine von drei Karten, einmal schmal in einer Seitenspalte. Media Queries helfen hier nur bedingt, denn sie fragen das Browserfenster ab, nicht den Platz, den der Baustein tatsächlich hat. Container Queries drehen die Frage um. Dieser Leitfaden zeigt, wie sie funktionieren, wie du sie in Tailwind einsetzt und wo sie an Grenzen stoßen.
- Container Queries fragen nach der Breite des Slots, in dem ein Baustein liegt, nicht nach der des Fensters. Derselbe Block passt sich überall an, wo er landet.
- Der Wrapper wird zum Container, das Element darin reagiert. Ein Baustein braucht dafür meist ein zusätzliches Element außen herum.
- In Tailwind v4 sind sie eingebaut: @container am Wrapper, @md: und Freunde an den Teilen. Ein eigenes Plugin ist nicht mehr nötig.
- Media Queries bleiben für das große Layout richtig. Container Queries sind für den einzelnen Baustein da, und beides zusammen ist der Normalfall.
Warum Media Queries hier zu kurz greifen
Eine Media Query stellt immer dieselbe Frage: Wie breit ist das Browserfenster? Für das große Layout einer Seite ist das genau richtig. Ein einzelner Baustein interessiert sich aber nicht für das Fenster, sondern für den Platz, den er an seiner Stelle hat.
Stell dir dieselbe Karte an drei Orten vor: über die volle Breite einer Landingpage, als eine von drei Spalten in einem Raster und schmal in einer Seitenspalte. Das Fenster ist im Raster und in der Seitenspalte gleich breit, der Platz für die Karte ist es nicht. Die Media Query sieht keinen Unterschied und liefert in beiden Fällen dieselbe Fassung.
Die Folge kennt jeder, der Bausteine wiederverwendet: Man baut Sonderfälle je Einbauort, oder der Baustein bricht in der schmalen Spalte um. Container Queries lösen das, indem sie nicht das Fenster messen, sondern den Container.
Media Query fragt das Fenster. Container Query fragt den Platz, den der Baustein wirklich hat.
Was eine Container Query misst
Damit ein Bereich abgefragt werden kann, muss er sich zuerst als Container zu erkennen geben. In reinem CSS geschieht das über container-type: inline-size. Diese Angabe sagt dem Browser: Dieses Element hat eine Breite, nach der Kinder fragen dürfen.
Das Wort inline-size ist wichtig. Es steht für die Breite im normalen Schreibfluss und beschränkt die Abfrage bewusst auf eine Richtung. Das ist gewollt, denn nur so bleibt die Höhe frei, sich aus dem Inhalt zu ergeben, ohne dass Layout und Abfrage sich gegenseitig blockieren.
Die Kinder fragen dann mit @container ab, nicht mit @media. Ab einer bestimmten Container-Breite greifen andere Regeln. Der Rest der Seite und das Fenster bleiben dabei außen vor.
<section className=" px-6"> <div className="mx-auto flex flex-col "> <p>Kicker</p> <h1>Überschrift</h1> <p>Zwei Sätze</p> <div className="flex "> <a>Termin buchen</a> <a>Projekte</a> </div> </div></section>
Zeig auf eine markierte Klasse, dann siehst du ihre Stelle in der Vorschau.
Der Wrapper meldet sich als Container. Die Karte darin fragt nach seiner Breite, nicht nach der des Fensters.
.slot { container-type: inline-size;} @container (min-width: 28rem) { .card { display: flex; gap: 1rem; }}
In Tailwind einrichten
In Tailwind fällt der Umweg über eigenes CSS weg. Der Wrapper bekommt die Klasse @container, und die Teile darin bekommen Schwellen wie @md: statt md:. Das Kürzel @md steht dabei nicht für das Fenster, sondern für die Breite des Containers.
Die Schwellen sind dieselben Namen, die du von den normalen Breakpoints kennst, nur eben auf den Container bezogen: @sm, @md, @lg und so weiter. So bleibt der Code lesbar, und man sieht am @ sofort, dass hier der Container gemeint ist und nicht das Fenster.
Der Aufbau ist damit immer gleich: ein Wrapper mit @container, darin das Element mit den @-Schwellen. Genau diese Trennung ist der Grund, warum ein Baustein aus der Library meist ein zusätzliches Element außen herum bekommt.
<div className="@container"> <article className="flex flex-col @md:flex-row @md:gap-4"> <img className="w-full @md:w-40" /> <div className="p-4"> <h3 className="text-base @md:text-lg">Titel</h3> </div> </article></div>
Gute Heroes nehmen Entscheidungen ab.
Drei Anordnungen, die tragen. Welche passt, entscheidet das Bildmaterial, nicht der Geschmack.
Benannte Container für verschachtelte Fälle
Eine Schwelle wie @md: fragt immer den nächsten Container darüber. Solange es nur einen gibt, ist das eindeutig. Sobald Container ineinander liegen, kann es der falsche sein: Eine Karte, die selbst ein Container ist und darin ein Medienfeld als weiterer Container, führt schnell dazu, dass ein Teil den inneren statt den äußeren fragt.
Dafür gibt es Namen. Der Wrapper bekommt @container/card, das Medienfeld @container/media, und die Teile fragen gezielt mit @md/card: oder @lg/card:. So steht im Code, welcher Container gemeint ist, und die Abfrage springt nicht auf den nächstbesten.
In der Praxis lohnt sich ein Name, sobald ein Baustein selbst wieder Bausteine enthält. Ein einzelner, flacher Container kommt ohne Namen aus.
<div className="@container/card"> <div className="@container/media"> <img className="w-full @md/card:w-40" /> </div> <p className="text-sm @lg/card:text-base">Beschreibung</p></div>
Einheiten, die mitwachsen
Container Queries schalten Regeln an Schwellen um. Manchmal will man aber keinen Sprung, sondern einen weichen Verlauf: Schrift oder Abstände, die mit der Breite des Containers mitwachsen. Dafür gibt es eigene Einheiten.
Die wichtigste ist cqi, ein Prozent der Inline-Breite des Containers. In einer clamp-Angabe zwischen einem kleinsten und einem größten Wert ergibt das eine Schriftgröße, die sich am Platz des Bausteins orientiert und nicht am Fenster. Daneben gibt es cqw und cqb sowie cqmin und cqmax für die jeweils kleinere oder größere Kante.
So bleibt eine Überschrift in der schmalen Spalte ruhig und in der vollen Breite groß, ohne dass man je Einbauort eine eigene Größe pflegt.
.card h3 { font-size: clamp(1rem, 4cqi, 1.5rem);}
cqi misst den Container, nicht das Fenster. Die Schrift folgt dem Slot, in dem sie steht.
Wo Container Queries an Grenzen stoßen
Container Queries sind seit 2023 in allen großen Browsern verfügbar, die Breitenabfrage kannst du also ohne Vorbehalt einsetzen. Ein paar Regeln der Mechanik sollte man trotzdem kennen, sonst sucht man an der falschen Stelle nach dem Fehler.
- Das Element bekommt @container und die Schwellen zugleich. Es passiert nichts, denn ein Container misst nur seine Kinder.
- container-type: inline-size setzen und dann nach der Höhe fragen. Die Höhe bleibt außen vor.
- Jeder Block wird vorsorglich zum Container. Das kostet Rechenzeit an Stellen, wo die Breite ohnehin feststeht.
- Ein Wrapper wird zum Container, das Element darin reagiert. Ein zusätzliches div genügt.
- Für die Breite reicht inline-size. Nur wo wirklich die Höhe zählt, kommt size mit bekannter Höhe dazu.
- Container nur dort, wo derselbe Baustein in verschieden breiten Slots landet.
Wann welche Query
Container Queries ersetzen Media Queries nicht, sie ergänzen sie. Die Frage ist nicht entweder oder, sondern welche Frage zur Sache passt.
- Gleicher Baustein, verschiedene Slots. Hier ist die Container Query richtig: eine Karte, die in Raster, Seitenspalte und voller Breite gleichermaßen sitzen soll.
- Das große Layout der Seite. Spaltenzahl, Navigation und die Ränder am Fensterrand bleiben Sache der Media Query. Sie beziehen sich auf das Gerät, nicht auf einen einzelnen Baustein.
- Beides zusammen. Der Normalfall: die Media Query ordnet das Raster, die Container Query formt den Baustein darin. Sie schließen sich nicht aus.
- Feinheiten am Gerät. prefers-reduced-motion, prefers-color-scheme und die Zeigergenauigkeit fragen weiter das Gerät ab, nicht den Container.
Für eine Bibliothek aus Bausteinen ist meist der Platz die richtige Frage, nicht das Fenster.




