Abschnitt 9 · Lektion 8
Gleiche Höhen und die klebende Fußzeile
Drei Karten sind gleich hoch, und ihre Buttons sitzen trotzdem auf drei verschiedenen Höhen. Dazu kommt eine Seite mit wenig Inhalt, deren Fußzeile mitten im Bild hängt. Hinter beiden steckt dieselbe Idee. Du gibst den freien Platz in einer Flex-Spalte gezielt an eine Stelle, und das sind jeweils nur ein paar Zeilen.
Gleich hoch, aber nicht unten
<div class="rezepte">
<article class="rezept">
<h3>Linsensuppe</h3>
<p>Rote Linsen, fertig in zwanzig Minuten.</p>
<a class="button" href="#">Zum Rezept</a>
</article>
<article class="rezept">
<h3>Kartoffelsalat</h3>
<p>Mit Brühe statt Mayonnaise, so wie er im Süden auf den Tisch kommt, und am besten noch lauwarm gegessen.</p>
<a class="button" href="#">Zum Rezept</a>
</article>
<article class="rezept">
<h3>Ofengemüse</h3>
<p>Was der Kühlschrank hergibt, ein Blech und vierzig Minuten.</p>
<a class="button" href="#">Zum Rezept</a>
</article>
</div> *,
*::before,
*::after {
box-sizing: border-box;
}
body {
font-family: system-ui, sans-serif;
line-height: 1.5;
background-color: #fafaf9;
}
/* Die drei Karten sind gleich hoch, dafür sorgt
stretch von allein. Die Buttons sitzen trotzdem auf
drei verschiedenen Höhen, denn jeder steht einfach
da, wo sein Text aufhört. */
.rezepte {
display: flex;
gap: 16px;
}
.rezept {
padding: 16px;
border-radius: 12px;
background-color: #ffffff;
}
.rezept h3 {
margin: 0 0 4px 0;
}
.rezept p {
margin: 0 0 16px 0;
color: #52525b;
}
.button {
padding: 8px 16px;
border-radius: 8px;
font-weight: 700;
text-decoration: none;
color: #ffffff;
background-color: #15803d;
} Die drei Karten im ersten Beispiel sind gleich hoch. Dafür hat niemand etwas getan. align-items steht auf seinem Standard, und der streckt Flex-Items über die volle Querachse. Das kennst du aus 9.4.
Die Buttons sitzen trotzdem auf drei verschiedenen Höhen. Auch das ist folgerichtig, denn innerhalb einer Karte ist nichts Flexbox. Dort stehen Überschrift und Text als ganz normale Blöcke untereinander. Darunter kommt der Button als Link in seiner eigenen Zeile, und der steht eben da, wo der Text aufhört.
Es fehlt also nicht eine Angabe an den Buttons, sondern eine Ebene tiefer ein zweiter Container.
Der automatische Außenabstand
<div class="rezepte">
<article class="rezept">
<h3>Linsensuppe</h3>
<p>Rote Linsen, fertig in zwanzig Minuten.</p>
<a class="button" href="#">Zum Rezept</a>
</article>
<article class="rezept">
<h3>Kartoffelsalat</h3>
<p>Mit Brühe statt Mayonnaise, so wie er im Süden auf den Tisch kommt, und am besten noch lauwarm gegessen.</p>
<a class="button" href="#">Zum Rezept</a>
</article>
<article class="rezept">
<h3>Ofengemüse</h3>
<p>Was der Kühlschrank hergibt, ein Blech und vierzig Minuten.</p>
<a class="button" href="#">Zum Rezept</a>
</article>
</div> *,
*::before,
*::after {
box-sizing: border-box;
}
body {
font-family: system-ui, sans-serif;
line-height: 1.5;
background-color: #fafaf9;
}
.rezepte {
display: flex;
gap: 16px;
}
/* Die Karte wird selbst zum Flex-Container, und zwar
als Spalte. Damit läuft ihre Hauptachse nach unten,
und darauf kann ein automatischer Außenabstand
wirken. */
.rezept {
display: flex;
flex-direction: column;
padding: 16px;
border-radius: 12px;
background-color: #ffffff;
}
.rezept h3 {
margin: 0 0 4px 0;
}
.rezept p {
margin: 0 0 16px 0;
color: #52525b;
}
/* auto frisst den ganzen freien Platz über dem Button.
align-self hält ihn schmal, sonst zöge stretch ihn
über die volle Kartenbreite. */
.button {
margin-top: auto;
align-self: flex-start;
padding: 8px 16px;
border-radius: 8px;
font-weight: 700;
text-decoration: none;
color: #ffffff;
background-color: #15803d;
} Die Karte wird selbst zum Flex-Container, und zwar als Spalte. Ihre Hauptachse läuft damit von oben nach unten, und der Button ist jetzt ein Flex-Item auf dieser Achse, genau wie Überschrift und Text über ihm.
Hier greift die Regel aus 9.3, die dort für Kopfzeilen gedacht war. Ein automatischer Außenabstand frisst in Flexbox den gesamten freien Platz auf seiner Seite. margin-top: auto am Button sammelt also allen Platz über ihm ein und drückt ihn an die Unterkante.
Dazu gehört als Zweites align-self: flex-start. Ohne das zieht stretch den Button über die volle Kartenbreite, denn in einer Spalte ist die Querachse waagerecht.
Du brauchst dabei keine Höhe an der Karte, kein position: absolute am Button und kein padding-bottom, das zum Button passen muss. Das Ergebnis stimmt auch dann noch, wenn ein Text drei Zeilen länger wird.
Übrigens lässt sich margin-top: auto nicht prüfen. Der berechnete Wert ist der ausgerechnete Pixelwert, und der ist in jeder Karte ein anderer, weil jede Karte unterschiedlich viel Text hat. Gemessen wird deshalb das Ergebnis. Liegen die Buttons auf einer Linie, sind die Karten gleich hoch und die Buttons unten. Eine einzige Prüfung reicht dann für zwei Eigenschaften.
Die Fußzeile, die unten bleibt
<header>Portfolio</header>
<main>
<p>Wenig Inhalt. In diesem Fall hängt eine Fußzeile
ohne Zutun mitten auf der Seite.</p>
</main>
<footer>Impressum und Datenschutz</footer> *,
*::before,
*::after {
box-sizing: border-box;
}
/* Drei Zutaten. Der body ist mindestens so hoch wie
der sichtbare Bereich und eine Spalte, und der
Hauptbereich nimmt sich alles, was darin übrig
bleibt. Die Fußzeile wird dadurch nach unten geschoben,
ohne selbst etwas dafür zu tun. */
body {
display: flex;
flex-direction: column;
min-height: 100dvh;
margin: 0;
font-family: system-ui, sans-serif;
line-height: 1.5;
background-color: #f4f4f5;
}
header,
footer {
padding: 16px 24px;
font-weight: 700;
color: #ffffff;
background-color: #18181b;
}
main {
flex-grow: 1;
padding: 24px;
}
main p {
margin: 0;
max-width: 46ch;
color: #52525b;
} Dasselbe Prinzip, eine Ebene höher. Eine Seite mit wenig Inhalt hat ihre Fußzeile mitten im Bild, und darunter steht weiße Fläche. Das sieht nach einem Fehler aus, ist aber nur eine Seite, die kürzer ist als der Bildschirm.
Es braucht drei Zutaten.
bodybekommtmin-height: 100dvh, ist also mindestens so hoch wie der sichtbare Bereich.bodywird eine Flex-Spalte.mainbekommtflex-grow: 1und nimmt sich damit den gesamten Überschuss.
Die Fußzeile wird dadurch nach unten geschoben, ohne selbst eine einzige Angabe zu bekommen. Wird der Inhalt länger als der Bildschirm, rutscht sie einfach mit nach unten, denn es ist eine Mindest- und keine Festhöhe.
100vh ist auf Mobilgeräten die falsche Zahl. Sie rechnet mit dem Bereich ohne Adressleiste. Beim Laden ist die Leiste aber noch da, und deshalb ragt die Fußzeile beim ersten Blick knapp aus dem Bild. 100dvh meint den tatsächlich sichtbaren Bereich und passt sich an, wenn die Leiste ein- und ausfährt. Ich nehme deshalb dvh, es kostet nichts.
In der Aufgabe sind die Karten schon gleich hoch, ihre Buttons aber nicht unten, und die Fußzeile hängt mitten auf der Seite.
Zum Mitnehmen
Freier Platz in einer Flex-Spalte lässt sich gezielt an eine Stelle geben. In der Karte schluckt ihn margin-top: auto über dem Button, auf der Seite nimmt ihn main mit flex-grow: 1, solange body mindestens 100dvh hoch ist.
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.