CSS Container Queries: A praktischer Leitfodn
Media Queries beantworten nur oane Frog: Wie groß is da Viewport? Des is bei de meisten Komponenten de falsche Frog, weil's a Card, a Sidebar-Widget oda a Produktkachl wurscht is, wie breit des Browserfenster is - sie interessiert, wie vül Platz sie hot, und des hängt davon ab, wo's im Layout hingstöt wird. Container Queries beantworten de Frog, de Komponenten wirklich brauchn.
Des Problem mit Responsive Design nur auf Basis vo Media Queries
Sogn ma, du boust a <card>-Komponente, de von horizontalem auf vertikales Layout wechseln soi, wenn's eng wird. Mit Media Queries muasst raten, bei wöcher Viewport-Breite des passiern soi:
.card {
display: flex;
flex-direction: row;
}
@media (max-width: 500px) {
.card {
flex-direction: column;
}
}
Des funktioniert super, wenn de Card imma fost den ganzen Viewport einnimmt. Aber stö de söbe Card in a schmale Sidebar auf an 1400px breiten Desktop-Bildschirm, und sie kriagt nia des vertikale Layout, des sie eigentlich brauchat - da Viewport is riesig, obwoi da verfügbare Platz vo da Card winzig is. Da Auftritt vo da Komponente hängt an was, wos sie ned im Griff hot: wo's da Parent hinstöt.
An Containment-Kontext deklariern
Container Queries drehn de Frog um: Statt "wie breit is da Viewport" fragst "wie breit is mei nächster Vorfahre, der si als Query-Container zur Verfügung gstöt hot". Aktiviern tuast des an am Element mit container-type:
.card-grid {
container-type: inline-size;
container-name: card-grid;
}
inline-size heißt "de Breite vom Container verfolgn" (da übliche Foi für horizontale Layout-Entscheidungen). container-name is optional - damit kannst an bestimmten Vorfahrn-Container ansprechen, wenn mehrere Container verschachtelt sand, statt nur "den nächsten" abzufragn.
Gegn den Container abfrogn
Wenn's Containment deklariert is, kinnan Nachkommen die Größe vom Container obfrogn statt die vom Viewport:
.card {
display: flex;
flex-direction: column;
gap: 8px;
}
@container card-grid (min-width: 400px) {
.card {
flex-direction: row;
gap: 16px;
}
}
Jetzt wird de söbe .card-Komponente horizontal, wenn 400px+ Container-Breite zur Verfügung stengan - ob's jetzt alloa auf ana breiten Seitn is oda eine von drei Spoitn auf ana schmäleren. De Komponente reagiert auf ihren tatsächlichen Platz, ned auf a Viewport-Zoi, de mit ihr nix zum tun hom muass.
Container-Query-Einheiten
Neben @container gibt's a passendes Set an Längeneinheiten, de gegn den Query-Container statt gegn den Viewport aufgelöst wern: cqw, cqh, cqi, cqb, cqmin, cqmax (analog zu vw/vh/vmin/vmax, aber container-relativ). Des is nützlich für fließende Typografie, de mit da eigenen Box von da Komponente skaliern soi statt mit da ganzn Seitn:
.card-title {
font-size: clamp(14px, 5cqi, 22px);
}
5cqi san 5 % vo da Inline-Größe vom Container - da Titel wird also größer, wenn de Card breiter wird, begrenzt zwischn 14px und 22px, unabhängig davon, wos de Viewport-Breite vom Rest der Seitn grod mocht.
A häufige Falln: Den eigenen Container obfrogn
container-type etabliert Containment an am Element, und @container-Queries schaun auf den nächsten Vorfahrn mit dem Containment - a Element kann si ned söba obfrogn:
/* This does NOT work as you might expect */
.card {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
/* .card can't query the container-type it declares on itself */
}
}
De Lösung is des Muster aus dem früheren Beispiel: container-type aufs Parent (.card-grid) setzn und von den Kindern (.card) aus obfrogn. Des bringt Leit durchananda, weil's genau umgekehrt is, wia ma's natürlich machen würd - ma wü, dass de Card auf ihre eigene Größe reagiert, aber des Containment muass an Level weiter oben liegn. Kopf einschalten, du Tschapperl!
Browser-Support und Fallback
Container Queries werdn in de aktuellen Versionen von Chrome, Firefox, Safari und Edge solide unterstützt. Für ois, wos auf wirklich oidn Browsern laufn muass, lasst @supports an Media-Query-Fallback zu:
.card {
flex-direction: column;
}
@media (min-width: 700px) {
.card {
flex-direction: row;
}
}
@supports (container-type: inline-size) {
@media (min-width: 700px) {
.card {
flex-direction: column; /* undo the media-query version */
}
}
.card-grid {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
flex-direction: row;
}
}
}
Fazit
Media Queries beschreibn den Viewport; Container Queries beschreibn den tatsächlich verfügbaren Platz vo da Komponente, und des is fost imma des, wos ma ursprünglich fragn wollt. Wennst scho amoi a Komponente gschriebn host, de oben auf da Seitn passt und falsch ausschaut, sobois sie in ana Sidebar wiederverwendet wird, dann is des genau des Problem, für des's Container Queries gibt.