CSS-Kurs / Container Queries für wiederverwendbare Komponenten
Container-Größenabfragen lassen eine Komponente auf die Größe eines geeigneten übergeordneten Containers reagieren, und nicht nur auf den Viewport. Deklarieren Sie einen Abfrage-Container mit container-type und verwende dann @container, um die Nachkommen-Stile bei der entsprechenden Größe zu ändern.
Viewport- und Container-Bedingungen vergleichen
Selbst wenn die Browserbreite 1200px beträgt, variiert die richtige Platzierung je nachdem, ob sich die Karte im 700px breiten Fließtextbereich oder im 300px breiten Seitenleistenbereich befindet. Es ist schwierig, diesen Unterschied nur mit den Media Queries und inhaltsabhängige Breakpoints auszudrücken, wenn die beiden Karten dieselben Viewport-Bedingungen teilen. Beim Wiederverwenden von Teilen können Sie layoutspezifische Ausnahmeregeln reduzieren, indem Sie deren interne Konfiguration basierend auf der Breite des übergeordneten Elements ändern.
| Aufteilung | Beurteilungskriterien | angemessene Rolle |
|---|---|---|
| @media | Umgebung wie Viewport-Breite | Anzahl der Spalten über die Seite, Position der Seitenleiste |
| @container | Größe des ausgewählten übergeordneten Containers usw. | Platzierung von Bildern und Text innerhalb der Karte, Abstand zwischen den Teilen |
Container-Abfragen vergleichen auch die Breite des bedingten Ausdrucks, anstatt „horizontal anordnen, wenn der Bildschirm horizontal ist.“ Wenn die Seitenleiste größer als 30rem wird, können die Karten darin ebenfalls horizontal angeordnet werden. Wenn Sie immer eine schmale Seitenleiste wünschen, sollten Sie auch eine maximale Breite im übergeordneten Layout angeben.
Einen Größenabfrage-Container deklarieren
.slot { container: panel / inline-size; }
@container panel (min-width: 30rem) {
.card { display: grid; grid-template-columns: 8rem minmax(0, 1fr); gap: 1rem; }
}
container: panel / inline-size deklariert den Namen panel und Inline-Größen-Einschränkung. Beim horizontalen Schreiben ist die Inline-Dimension horizontal; beim vertikalen Schreiben ändert sich diese Zuordnung. Stellen Sie die Breite des Containers über sein äußeres Block-Layout oder Grid-Track bereit, damit die Karte eine sinnvolle Größe für Abfragen hat. Siehe CSS Grid Grundlagen: Tracks, Linien und Elementplatzierung.
Das übergeordnete Element zur Bewertung der Bedingung ist .slot und das Nachfahrelement, das den bedingten Stil erhält, ist .card. Schreiben Sie nicht in einer Struktur, die die Karte selbst verändert, indem Sie die Größe der Karte selbst abfragen. Um das Problem zu vermeiden, dass Bedingungen immer wieder umgekehrt werden, während sich die Größe ändert, erfolgen Größenabfragen relativ zu geeigneten Vorfahren.
inline-size Containment macht die Inline-Größe des Containers unabhängig von den Inhaltsbeiträgen seiner Nachkommen. Ein Shrink-to-Fit-Container kann daher unerwartet klein werden. Hier liefert ein Block- oder Grid-Track seine Breite. Die Verwendung von size Containment beeinflusst auch die andere Achse und kann eine inhaltsbasierte Höhe zusammenbrechen lassen, daher wählen Sie die Containment-Einstellung bewusst. Für weitere Details siehe Sie können das Ausmaß der Größenisolation in der Beschreibung des Container-Typs auf MDN sehen.
Verwenden Sie eine Karte bei unterschiedlichen Elternbreiten
Speichern Sie es als container-card.html und öffnen Sie es in Ihrem Browser. Das Farbkästchen ist ein Beispiel-Element, das den Bildbereich darstellt, daher gibt es keine separate Bilddatei. Auf größeren Bildschirmen trennen Sie den Haupttext und eine Seitenleiste von bis zu 20rem, und bei 44rem oder weniger platzieren Sie die beiden Bereiche in einer Spalte.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>container-card.html</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font: 1rem/1.6 sans-serif; color: #243447; }
h1, h2, p { margin-top: 0; } a { color: #145f8f; }
a:focus-visible, button:focus-visible, input:focus-visible { outline: 3px solid #ac4100; outline-offset: 3px; }
.layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 20rem); gap: 1rem; width: min(100%, 75rem); margin-inline: auto; padding: 1rem; }
.slot { min-width: 0; container: panel / inline-size; }
.card { min-width: 0; padding: 1rem; background: #e8f3fa; overflow-wrap: anywhere; }
.media { min-height: 7rem; background: #287699; }
.card h2 { font-size: 1.25rem; } .card p { margin-bottom: 0; }
@container panel (min-width: 30rem) {
.card { display: grid; grid-template-columns: 8rem minmax(0, 1fr); gap: 1rem; align-items: start; }
}
@media (max-width: 44rem) { .layout { grid-template-columns: minmax(0, 1fr); } }
</style>
</head>
<body>
<div class="layout">
<main class="slot"><article class="card"><div class="media" aria-hidden="true"></div><div><h2>Card in the main content area</h2><p>The image and text appear side by side when the parent is at least 30rem wide.</p></div></article></main>
<aside class="slot"><article class="card"><div class="media" aria-hidden="true"></div><div><h2>The same card in a sidebar</h2><p>The sidebar in this example stays at or below 20rem even on a wide screen, so the card keeps its vertical layout.</p></div></article></aside>
</div>
</body>
</html>
Bei einer Root-Schriftgröße von 16px entsprechen die 30rem dieser Containerbedingung 480px. Die 44rem-Medienbedingung richtet sich dagegen nach der anfänglichen Schriftgröße. Wenn der Body-Elternteil auf einem großen Bildschirm 480px oder mehr beträgt, wird der Inhalt der Karte in zwei Spalten angeordnet, und in einer Seitenleiste von bis zu 320px wird der Inhalt der Karte vertikal angeordnet. Auf schmalen Bildschirmen, während die Seitenleiste nach unten verschoben wird, kann ihr Elternteil breiter werden. Daher ist es normal, dass beide Karten auf einem 600px-Bildschirm horizontal platziert werden, solange die Breite des Elternteils die Bedingungen erfüllt.
Die äußere Bedingung von 44rem und die innere Bedingung von 30rem lösen unterschiedliche Probleme. Die erste Bedingung bestimmt, wie der Bereich auf der gesamten Seite platziert wird, und die zweite Bedingung bestimmt, wie Bilder und Text innerhalb des jeder Karte zugewiesenen Raums platziert werden. Jede Karte wählt unter ihren Vorfahren den nächsten geeigneten Größencontainer mit dem Namen panel. Erst an diesem Container wird die Breitenbedingung geprüft. Ist sie dort falsch, wird nicht ersatzweise ein weiter außen liegender, breiterer panel-Container verwendet.
Wählen Sie die nächsten und benannten Container aus
Eine unbenannte Größenabfrage wählt den nächstgelegenen übergeordneten Container aus, dessen Bedingungen abgefragt werden können. Selbst wenn der äußere Bereich breit ist, können die Ergebnisse variieren, wenn ein schmalerer Container in der Mitte hinzugefügt wird. Sie können diesen Unterschied separat sehen, indem Sie das folgende Beispiel als container-nested.html speichern.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>container-nested.html</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font: 1rem/1.6 sans-serif; color: #243447; }
h1, h2, p { margin-top: 0; } a { color: #145f8f; }
a:focus-visible, button:focus-visible, input:focus-visible { outline: 3px solid #ac4100; outline-offset: 3px; }
main { width: min(100%, 42rem); padding: 1rem; }
.outer { width: 100%; container: outer / inline-size; border: 2px solid #789; padding: 1rem; }
.inner { width: min(100%, 17rem); container-type: inline-size; }
.card { padding: 1rem; background: #e8f3fa; overflow-wrap: anywhere; }
.media { min-height: 5rem; background: #287699; }
@container (min-width: 30rem) {
.card { display: grid; grid-template-columns: 5rem minmax(0, 1fr); gap: 1rem; }
}
</style>
</head>
<body>
<main><h1>Which parent's width is queried?</h1><div class="outer"><div class="inner"><article class="card"><div class="media" aria-hidden="true"></div><p>The nearest inner container has a maximum of 17rem.</p></article></div></div></main>
</body>
</html>
Auf breiten Bildschirmen ist der äußere Container größer als 30rem, aber der innere Container ist höchstens 17rem. Die unbenannte Bedingung wählt den nächstgelegenen Inneren aus, sodass die Karten vertikal angeordnet werden. Behalten Sie den übrigen Code bei und ersetzen Sie @container (min-width: 30rem) durch Folgendes:
@container outer (min-width: 30rem) {
.card { display: grid; grid-template-columns: 5rem minmax(0, 1fr); gap: 1rem; }
}
Jetzt wählen wir den äußeren Vorfahren mit dem Namen ‚outer‘ aus, sodass die Karte auf dem breiten Bildschirm horizontal angeordnet wird. Die Karte selbst liegt immer noch innerhalb des maximalen Rahmens von 17rem, prüfen Sie deshalb gesondert, ob der verbleibende Platz für den Text ausreicht. Der Name ist keine Eigenschaft, die automatisch inkorrekte Standards korrigiert, sondern eine Funktion, die angibt, welchen Vorfahren man als Standard verwendet. Stellen Sie nach dem Vergleich die unbenannte Bedingung wieder her.
Prüfen Sie Abfragen, die nicht zutreffen
- Prüfen Sie, ob das Ziel des bedingten Selektors ein Nachkomme des Containers ist. Überprüfen Sie, dass Sie nicht versuchen, denselben Stil auf das übergeordnete Element selbst anzuwenden.
- Überprüfen Sie container-type des übergeordneten Elements und die tatsächliche Inhaltsbreite in den Entwicklertools. Es darf keine Verwechslung zwischen der äußeren Breite, einschließlich Padding und Rahmen, und der zu suchenden Größe geben.
- Überprüfen Sie, ob ein neuer Container erstellt wurde, und geben Sie bei Bedarf die Kriterien mit container-name an.
- Wenn Sie nur container-type auf normal ändern, können Sie den Unterschied erkennen, dass die Größenabfrage nicht angewendet wird. Nach der Bestätigung stellen Sie wieder auf inline-size zurück.
Behalten Sie eine gut lesbare vertikale Karte als Ausgangsbasis bei und fügen Sie dann eine horizontale Anordnung hinzu, wenn die Containerabfrage zutrifft. Die Ausgangsbasis dient auch Browsern, die die Größenabfrage nicht unterstützen. Überprüfen Sie die Unterstützung und das Verhalten in den Browsern, die Ihre Leser tatsächlich verwenden. Siehe MDN: Containergröße und Stilabfragen.




