Abschnitt 10 · Lektion 2
repeat(), minmax() und auto-fit
In der letzten Lektion hast du Spalten von Hand abgezählt. Das geht bei dreien, und es geht nicht mehr bei zwölf. Diese Lektion räumt das Abzählen weg und baut daraus ein Raster, das sich selbst an die Breite anpasst.
repeat
<p class="titel">vier Spalten von Hand</p>
<div class="raster hand">
<div class="zelle">1</div><div class="zelle">2</div>
<div class="zelle">3</div><div class="zelle">4</div>
</div>
<p class="titel">dieselben vier mit repeat</p>
<div class="raster kurz">
<div class="zelle">1</div><div class="zelle">2</div>
<div class="zelle">3</div><div class="zelle">4</div>
</div>
<p class="titel">repeat lässt sich mit festen Spuren mischen</p>
<div class="raster gemischt">
<div class="zelle">fest</div><div class="zelle">1</div>
<div class="zelle">2</div><div class="zelle">fest</div>
</div> *,
*::before,
*::after {
box-sizing: border-box;
}
body {
font-family: system-ui, sans-serif;
}
.titel {
margin-bottom: 4px;
font-size: 14px;
color: #52525b;
}
.raster {
display: grid;
gap: 12px;
margin-bottom: 20px;
}
.zelle {
padding: 16px;
font-weight: 700;
color: #ffffff;
background-color: #2563eb;
}
.hand {
grid-template-columns: 1fr 1fr 1fr 1fr;
}
.kurz {
grid-template-columns: repeat(4, 1fr);
}
/* repeat ist keine eigene Zeile, sondern ein Stück
der Spurliste. Davor und dahinter darf stehen,
was du willst. */
.gemischt {
grid-template-columns: 120px repeat(2, 1fr) 120px;
} repeat(4, 1fr) bedeutet “viermal 1fr”. Mehr steckt nicht dahinter, und trotzdem ändert es, was sich bequem schreiben lässt: repeat(12, 1fr) ist ein Zwölf-Spalten-Raster in einer Zeile.
Dass beide Schreibweisen dasselbe ergeben, ist keine Behauptung: Zeig auf die ersten beiden Raster, und im Reiter „Werte” steht beide Male dieselbe Zeile, in der schmalen Spalte grid-template-columns: 82px 82px 82px 82px. Im Reiter „Regeln” steht einmal 1fr 1fr 1fr 1fr und einmal repeat(4, 1fr). Der Unterschied liegt allein in der Datei.
Wichtig ist, dass repeat() kein Ersatz für die ganze Spurliste ist, sondern ein Stück davon. 120px repeat(2, 1fr) 120px ist völlig in Ordnung: feste Ränder außen, flexible Spalten innen. Wiederholen lässt sich auch ein Muster aus mehreren Spuren, repeat(3, 200px 1fr) legt sechs Spuren im Wechsel an.
minmax
<p class="titel">minmax(0, 1fr): die Spalten schrumpfen ohne Boden</p>
<div class="raster ohne">
<div class="karte">Ein Text, der schon zu eng steht.</div>
<div class="karte">Noch ein Text daneben.</div>
<div class="karte">Und ein dritter.</div>
<div class="karte">Und ein vierter.</div>
<div class="karte">Und ein fünfter.</div>
</div>
<p class="titel">minmax(200px, 1fr): unter 200px geht nichts</p>
<div class="raster mit">
<div class="karte">Ein Text, der jetzt Platz hat.</div>
<div class="karte">Noch ein Text daneben.</div>
<div class="karte">Und ein dritter.</div>
<div class="karte">Und ein vierter.</div>
<div class="karte">Und ein fünfter.</div>
</div> *,
*::before,
*::after {
box-sizing: border-box;
}
body {
font-family: system-ui, sans-serif;
line-height: 1.5;
}
.titel {
margin-bottom: 4px;
font-size: 14px;
color: #52525b;
}
.raster {
display: grid;
gap: 12px;
margin-bottom: 20px;
}
.karte {
padding: 12px;
border-radius: 8px;
background-color: #ffffff;
border: 1px solid #d4d4d8;
}
/* Die 0 nimmt der Spur ihren Boden. Ein nacktes 1fr
hätte einen: es ist die Kurzform für
minmax(auto, 1fr), und auto heißt "so schmal, wie
mein Inhalt gerade noch zulässt". Mit der 0 teilen
die fünf Spalten den Platz wirklich stur durch
fünf, egal wie wenig dabei herauskommt. */
.ohne {
grid-template-columns: repeat(5, minmax(0, 1fr));
}
/* minmax setzt einen Boden. Passen fünf Spuren zu
200px nicht mehr nebeneinander, läuft das Raster
über, statt die Spalten weiter zu quetschen. */
.mit {
grid-template-columns: repeat(5, minmax(200px, 1fr));
} 1fr hat einen Boden, den man ihm nicht ansieht. Es ist die Kurzform für minmax(auto, 1fr), und dieses auto heißt “so schmal, wie mein Inhalt gerade noch zulässt”. Fünf Spalten in einem schmalen Container schrumpfen also nicht bis auf null, sondern bis auf ihr längstes Wort. Zum Lesen hilft das wenig: eine Spur, die genau ein Wort breit ist, bricht danach jedes Wort einzeln um, und irgendwann läuft das Raster trotzdem über.
minmax(200px, 1fr) gibt einer Spur eine Untergrenze und lässt sie darüber wachsen. Unter 200px geht sie nicht, darüber nimmt sie ihren Anteil am freien Platz. Der Boden ist damit deiner statt der des Inhalts.
Was das in der schmalen Spalte heißt, steht im Streifen. Am oberen Raster mit minmax(0, 1fr) sind es fünf Spuren zu je gut 63 Pixeln, am unteren mit minmax(200px, 1fr) fünfmal glatte 200px. Fünfmal 200 plus vier Lücken sind 1048 Pixel in einem Kasten, der 364 breit ist: Eine Untergrenze verhandelt nicht, sie läuft lieber über. Genau deshalb steht in der Zeile, die du gleich schreibst, auto-fit daneben.
Und minmax(0, 1fr) macht das Gegenteil: Es nimmt der Spur den Boden ganz weg, sie darf dann schmaler werden als das, was in ihr steht. Genau das steht im oberen Beispiel, sonst sähen die beiden Raster einander viel ähnlicher. Gebraucht wird es überall dort, wo ein einzelner zu langer Inhalt sonst ein ganzes Raster auseinanderdrückt.
Zwei Werte, zwei Rollen, und man verwechselt sie leicht: der erste ist das Minimum, der zweite das Maximum. minmax(200px, 1fr) heißt “mindestens 200px, höchstens mein Anteil”. Andersherum geht es nicht. minmax(1fr, 200px) ist keine gültige Angabe, denn ein fr darf nur an der zweiten Stelle stehen. Der Browser wirft die ganze Deklaration weg, ohne etwas zu sagen, und dein Raster steht danach einspaltig da. Das ist derselbe Fall wie in 1.4: Ein ungültiger Wert meldet sich nicht, er hinterlässt eine Zeile, die es plötzlich nicht mehr gibt, und man sucht den Fehler woanders.
auto-fill und auto-fit
<p class="titel">auto-fill: die leeren Spuren bleiben stehen</p>
<div class="raster fill">
<div class="karte">Tipptrainer</div>
<div class="karte">Referenz</div>
</div>
<p class="titel">auto-fit: die leeren Spuren klappen zusammen</p>
<div class="raster fit">
<div class="karte">Tipptrainer</div>
<div class="karte">Referenz</div>
</div>
<p class="hinweis">
Mit vier oder mehr Karten sehen beide gleich aus. Der Unterschied
zeigt sich nur, wenn weniger Karten da sind als Spuren hineinpassen.
</p> *,
*::before,
*::after {
box-sizing: border-box;
}
body {
font-family: system-ui, sans-serif;
line-height: 1.5;
}
.titel {
margin-bottom: 4px;
font-size: 14px;
color: #52525b;
}
.raster {
display: grid;
gap: 16px;
margin-bottom: 20px;
}
.karte {
padding: 20px;
border-radius: 12px;
font-weight: 700;
color: #ffffff;
background-color: #2563eb;
}
/* Beide legen so viele Spuren an, wie hineinpassen.
auto-fill lässt die unbenutzten stehen, deshalb
bleiben die zwei Karten schmal am linken Rand. */
.fill {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
/* auto-fit klappt die unbenutzten auf Breite null
zusammen. Die zwei Karten teilen sich damit die
ganze Zeile. */
.fit {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.hinweis {
max-width: 56ch;
color: #52525b;
} Und jetzt kommt der Teil, der Grid von allem unterscheidet, was es vorher gab.
Statt einer Zahl darf in repeat() auch ein Schlüsselwort stehen. Beide legen so viele Spuren an, wie in den Container hineinpassen:
auto-filllässt die Spuren stehen, auch wenn nichts darin liegt.auto-fitklappt die leeren auf Breite null zusammen, sodass die vorhandenen Elemente den ganzen Platz füllen.
Den Unterschied siehst du nur, wenn weniger Elemente da sind als Spuren hineinpassen. Bei zwölf Karten in einem Raster für vier verhalten sich beide identisch, und deshalb hält man sie so lange für dasselbe. Und du brauchst Platz dafür: in der schmalen Spalte ist die Seite zu eng für mehrere Spuren, dort steht in beiden Rastern grid-template-columns: 364px, eine einzige Spur. Mach die Seite im Vollbild groß, dann steht sie auf den 900 Pixeln, für die das Beispiel gebaut ist.
Und dann lohnt der Blick in den Streifen mehr als der aufs Bild. Beim auto-fill-Raster steht dort grid-template-columns: 209px 209px 209px 209px, beim auto-fit-Raster 434px 434px 0px 0px. Vier Spuren gegen vier Spuren: auto-fit wirft die leeren nicht weg, es drückt sie auf null zusammen, und die beiden vollen nehmen sich den Platz. Auf dem Bild siehst du zweimal zwei Karten, einmal schmal und einmal breit. Im Streifen siehst du, warum.
Zusammen ergibt das die Zeile, die du gleich schreibst:
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
Übersetzt: “Leg so viele Spalten an, wie mit mindestens 260px hineinpassen, und lass sie den Platz gleichmäßig füllen.” Auf einem breiten Bildschirm sind das vier Spalten, auf einem Tablet zwei, auf dem Handy eine. Ohne Media Query, ohne Breakpoint, ohne eine einzige Zahl, die zu einer anderen passen muss.
Das ist übrigens keine Bequemlichkeit, sondern ein besseres Ergebnis. Eine Media Query kennt nur die Breite des Fensters. Das Raster hier kennt die Breite seines Containers, und die kann eine ganz andere sein, wenn es in einer Seitenspalte steckt.
Zum Mitnehmen
repeat(auto-fit, minmax(260px, 1fr)) ist die eine Zeile, die ein Kartenraster über alle Bildschirmgrößen trägt. Keine Media Query, keine Breakpoints, keine Zahlen, die zueinander passen müssen.
Jetzt du
Basis Konto, kostenlosZu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
Was in dieser Lektion steckt
-
Artikel mit 3 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe im Editor, direkt im Browser geprüft
Öffnet sich mit dem Basis Konto.