Die Mitgliederversammlung findet am 25.11.2023 um 10:00 statt; davor und danach gibt es Gelegenheiten zum gemütlichen Beisammensein.
Weitere Informationen und eine Anmeldemöglichkeit gibt es in der Veranstaltungs-Ankündigung.
CSS/Media Queries/Container Queries
Text-Info
- 20min
- mittel
- ● Einstieg in CSS
• CSS/Media Queries
Während Medienabfragen eine Methode zur Abfrage von Aspekten des Browsers oder der Geräteumgebung bieten, in der ein Dokument angezeigt wird (z. B. Abmessungen des Viewports oder Benutzereinstellungen), ermöglichen Containerabfragen das Testen von Aspekten von Elementen innerhalb des Dokuments (z. B. Rahmenabmessungen oder berechnete Stile).
Ein Abfragecontainer wird durch die Angabe der möglichen Abfragetypen unter Verwendung der Eigenschaft container-type (oder der shorthand container) erstellt. Stilregeln, die auf seine Nachkommen angewendet werden, können dann durch Abfragen mit der bedingten Gruppenregel @container konditioniert werden.
Inhaltsverzeichnis
Einsatz
Bei der Erstellung eines responsiven Designs verwenden Sie häufig eine Medienabfrage, um das Layout des Dokuments auf der Grundlage der Viewportbreite zu ändern.
Viele Designs haben jedoch gemeinsame Komponenten, die das Layout in Abhängigkeit von der verfügbaren Breite ihres Containers ändern. Dies muss sich nicht immer auf den Viewport beziehen, sondern auch darauf, wo im Layout die Komponente platziert ist.[1]
Anwendungsbeispiel
Cards sind eines der Entwurfsmuster, die für Container Queries geradezu prädestiniert scheinen. Sie sollen sich nicht nur responsiv über die Seitenbreite verteilen; sondern eben auch je nach verfügbarem Platz ihr Aussehen ändern.
container-type
Um Container-Abfragen zu verwenden, müssen Sie zunächst ein Wrapper-Element festlegen. Durch Hinzufügen der container-type-Eigenschaft mit einem Größenwert wird ein containment-context für dieses Eltern-Element erstellt. Das bedeutet, dass der Browser weiß, dass wir diesen Container später abfragen wollen. Sie können dann eine Abfrage schreiben, die sich auf diesen Containment-Kontext bezieht und nicht auf die Viewport-Größe, um Layout-Entscheidungen für eine Komponente zu treffen.
Eine Container-Abfrage wird mit @container erstellt. Damit wird der nächstgelegene containment-context abgefragt. Um die Karte nur dann zweispaltig darzustellen, wenn die Seitenleiste breiter als 40em ist, verwenden wir das folgende CSS:
.card-container {
container-type: inline-size;
}
.card {
}
@container (min-width: 40em){
.card {
display: grid;
grid-template-columns: 2fr 1fr;
}
}
Das Container-Parent mit der Klasse .card-container
erhält mit container-type
den Wert inline-size
.
Mit .card
erhält die Karte selbst (hier nicht dargestellte) Festlegungen.
Mit @container
wird nun bei einer Mindestbreite von 40em ein grid erstellt.
container-name
Problematisch wird dies, wenn Sie auf einer Seite mehrere Container erstellen wollen. Hier empfiehlt es sich, dem Eltern- oder Wrapper-Element mit Eigenschaft einen Namen zu geben:
.card-container {
container-type: inline-size;
container-name: card;
}
@container card (min-width: 40em){
.card {
display: grid;
grid-template-columns: 2fr 1fr;
}
}
Mit dem in container-name
festgelegten Namen card
kann die @container
-Abfrage fest mit dem Parent verknüpft werden. Dies schafft Übersicht!
container
container ist die zusammenfassende Eigenschaft von container-type und container-name:
.card-container {
container: card / inline-size;
}
@container card (width > 40em){
.card {
display: grid;
grid-template-columns: 2fr 1fr;
}
}
Die container-Eigenschaft erhält als Werte die durch ein /
getrennten Namen und Schlüsselwert.
Ist Ihnen aufgefallen, dass die Abfrage kürzer als gewohnt ist? In Stufe 4 der Media Queries Spezifikation ist eine für Programmierer ansprechendere Schreibweise hinzugekommen.
Mehrspaltiges Layout mit CSS Container Queries
In diesen zwei Beispielen soll nun die Funktionsweise gezeigt werden; zuerst mit nur einer Karte, später als komplexeres Beispiel:
<article class="card-container">
<div class="card">
<h3 class="card__title">Karte</h3>
<div class="content">
<p>...</p>
</div>
<img src="Landscape.svg" at="Landschaft mit Berg und Kirche als Symbolbild">
</div>
</article>
Als wrapper-Element verwenden wir ein article-Element, das eine passende Klasse erhält.
Unsere Karte besteht aus einem div mit einer h3-Überschrift, einem Inhaltsbereich (.content
) und einem Bild.
.card-container {
container: card/ inline-size;
}
@container card (width >= 30em) {
.card-container .card {
--color: pink;
grid-template-columns: 33% 1fr;
grid-template-areas: "image title"
"image content";
gap: 1em;
}
.card-container .card__title {
grid-area: title;
}
.card-container .card p {
grid-area: content;
}
.card-container .card img {
grid-area: image;
}
}
@container (width >= 50em) {
.card-container .card {
--color: skyblue;
grid-template-columns: 50% 12em 1fr;
grid-template-areas: "image title content";
}
}
.card {
display: grid;
}
Die Karte befindet sich im Container, den Sie mit der Maus größer oder kleiner ziehen können. Sobald die Containerabfrage greift, wird das Grid Layout aufgebaut und die Inhalte nebeneinander dargestellt. Zusätzlich wird die Hintergrundfarbe geändert.
Diese Karte soll nun in verschiedenen Containern verwendet werden. Es so aber weiterhin eine CSS-Festlegung „für ae Gelegenheiten geben“:
<article>
<div class="card-container">
<div class="card">
...
</div>
</div>
<div class="card-container">
<div class="card">
...
</div>
</div>
...
</article>
<aside class="card-container">
<div class="card">
...
</div>
</aside>
<footer class="card-container">
<div class="card">
...
</div>
</footer
Das CSS für den article verteilt die Karten nun über den verfügbaren Platz:
article {
display: flex;
flex-wrap: wrap;
gap: 1em;
}
article .card-container {
flex: 1 0 30%;
gap: 1em;
}
article .card {
min-height: 14em;
}
Die .card-container verteilen sich mit flex auf den verfügbaren Platz. Für schmale Viewports müsste man eine weitere Medienabfrage mit weniger SPaltne einbauen.
Zwischenfazit:
Ich bin nicht ganz zufrieden mit dem Ergebnis.
Ursprünglich wollte ich die cards im article mit grid-template-columns: repeat(auto-fit, minmax(min(12em, 100%), 1fr));
verteilen. Dabei bemerkte ich aber dass die Containerabfrage die Breite des Elternelements und nicht, wie von mir erwünscht - des vom Grid erzeugten Rasterfelds abfragt. Eigentlich logisch, erfordert hier aber die Anage eines Wrapper-Elements um jede einzelne Karte.
Andererseits wollte ich den verfügbaren Patz auf die Karten aufteilen, so dass ich mit der Flexbox-Lösung besser fahre. Für schmale Viewports wäre hier eine weitere media query nötig, was ich neben den wrapper-Elementen eigentlich vermeiden wollte.
Durch die Wrapper-Elemente haben die einzelnen Karten je nach Inhalt unterschiedliche Höhen - etwas, was mit Grid auch automatisch ausgeglichen würde. Ich würde dieses Beispiel am liebsten mit einem normalen Grid und einer eigenen Festlegung für Karten in einem Grid ohne Container Queries bauen. In der Zukunft finden sich hier vielleicht neue Ansätze.
--Matthias Scharwies (Diskussion) 06:50, 4. Aug. 2023 (CEST)
Container-Query-Einheiten
Das CSS Containment Module enthält neben den oben besprochenen Eigenschaften auch zahlreiche neue Einheiten. Container-Query-Längeneinheiten geben eine Länge relativ zu den Abmessungen eines Abfragecontainers an. Komponenten, die Längeneinheiten relativ zu ihrem Container verwenden, können flexibler in verschiedenen Containern verwendet werden, ohne dass konkrete Längenwerte neu berechnet werden müssen.[2][3]
Wer mit den Einheiten vw, vh etc. für Viewports bereits vertraut ist, wird hier wenig Startschwierigkeiten haben. Wenn sie sich innerhalb eines Containers befinden, werden die Containerabmessungen anstelle der Viewport-Abmessungen verwendet. Wenn sie sich nicht innerhalb eines Containers befinden, verwenden sie Werte der Viewport-Abmessungen.
Ein Vergleich mit „normalen“ relativen rems zeigt die Ersparnis:
.card__title {
font-size: 1rem;
}
/* The horizontal style, v1 */
@container (min-width: 400px) {
.card__title {
font-size: 1.15rem;
}
}
/* The horizontal style, v2 */
@container (min-width: 600px) {
.card__title {
font-size: 1.25rem;
}
}
/* The hero style */
@container (min-width: 800px) {
.card__title {
font-size: 2rem;
}
}
.card__title {
font-size: clamp(1rem, 3cqw, 2rem);
}
Im linken Beispiel wird die Schriftgröße von .card__title
mit 1rem festgesetzt und dann durch mehrere Media queries passend zur Viewportgröße festgelegt. Auf der rechten Seite wird dies durch eine einzige Deklaration erreicht. Die Schriftgröße wird mit einer clamp()-Funktion mit cqw auf 3% der Containerbreite festgelegt, minimal 1rem, maximal aber 2rem.[4]
Schriftgröße abhängig vom Container ändern
Oft möchte man die Überschrift über die gesamte Breite laufen lassen. Im pixelgenauen Layout kann so etwas mit Magic Numbers fest eingestellt werden. Jede Änderung der Breite zerschießt dann das Layout. Hier kann die Schriftgröße fließend „mitwachsen“:
<div class="container">
<div class="card"> … </div>
</div>
.container {
container-type: inline-size;
}
.card {
font-size: clamp(1em, 18cqi, 5em);
}
Als Wert für font-size wird in der CSS-Funktion clamp() eine variable Schriftgröße mit einer Mindest- und einer Maximalgröße angegeben. Die mittlere Angabe in clamp()
legt den Orientierungspunkt fest. Mit 18cqi
gestalten wir eine dynamische Schriftgröße auf Grundlage von 18% der Inline-Größe des Containers.
Polyfill
Mittlerweile (Stand Mai 2023) werden Container Queries von den letzten Versionen der Browser (Anteil: ca. 86%) unterstützt. Für ältere Versionen können Sie einen Polyfill von Chris Coyier verwenden.[5][6]
- GoogleChromeLabs auf github: container-query-polyfill von surma
// Support Test
const supportsContainerQueries = "container" in document.documentElement.style;
// Conditional Import
if (!supportsContainerQueries) {
import("https://cdn.skypack.dev/container-query-polyfill");
}
Siehe auch
Eigenschaften
Container-Einheiten
@-Regeln
Weblinks
- csswg: CSS Containment Module Level 3
- MDN: CSS Container Queries
- css-tricks: Next Gen CSS: @container Una Kravets, May 11, 2021
- ishadeed.com: CSS Container Query Units vom 18.09.2021
- smashing-magazine: A Primer On CSS Container Queries Stephanie Eckles, 11.05.2021
- Ahmad Shadeed hat sich schon früh mit Containerabfragen beschäftigt und verfügt über eine wachsende Sammlung von Beispielen, die auf alltäglichen Mustern basieren.[7][8]
Quellen
- ↑ Wann Media Queries an ihre Grenzen stoßen im Blog von kulturbanause
- ↑ MDN: Container query length units
- ↑ Container Units Should Be Pretty Handy (css-tricks.com)
- ↑ CSS Container Query Units von Ahmad Shadeed, 18 Sep 2021
- ↑ css-tricks: A New Container Query Polyfill That Just Works vom 06.01.2022
- ↑ github: GoogleChromeLabs /container-query-polyfill von surma
- ↑ css-tricks: iShadeed’s Container Queries Lab Geoff Graham on Sep 1, 2022
- ↑ iShadeed Lab - Container queries
deutsch
- kulturbanause: CSS Container Queries mit @container