Zum Inhalt
wannacode

Flexbox: Reihe und Spalte

Kurz gesagt: Flexbox ordnet Items entlang der Hauptachse in einer Reihe oder Spalte an, richtet sie auf der Querachse aus und verteilt den freien Platz mit flex-grow.

Problem

Die Kopfzeile in drei Zeilen

Die neue Kopfzeile des Shops soll eine Zeile sein: links das Logo, daneben das Menü, rechts der Warenkorb. Am Computer sind es drei Zeilen untereinander.

HTML, CSS, JS

Das CSS hat keinen Fehler. <nav> ist ein Blockelement, und Blockelemente stehen untereinander, jedes in einer ganzen Zeile. Links sind Inline-Elemente und stehen mit dem Text um sie herum in einer Zeile. Also steht das Logo in der ersten Zeile, das Menü in der zweiten und der Warenkorb in der dritten.

Die Idee

Container und Items

Die Kinder der Kopfzeile brauchen eine andere Art der Anordnung. Sie heißt display: flex am Elternelement:

header {
display: flex;
}
  • Das Element mit display: flex ist ein Flex-Container. Seine Kinder (nur die direkten) sind Flex-Items.
  • Die Items stehen entlang der Hauptachse nebeneinander. Standardmäßig läuft sie von links nach rechts. flex-direction: column dreht sie von oben nach unten.
  • Im rechten Winkel dazu liegt die Querachse.

Die Anordnung wird am Container festgelegt, nicht an den Kindern:

  • justify-content ordnet entlang der Hauptachse an: flex-start (am Anfang), center, flex-end, space-between (das erste am Anfang, das letzte am Ende, der Platz dazwischen).
  • align-items richtet entlang der Querachse aus: stretch (der Standard, alle so hoch wie die Zeile), center, flex-start, flex-end.
  • gap setzt gleich viel Platz zwischen die Items, nichts vor das erste und nichts hinter das letzte.

Ein Element kann gleichzeitig Flex-Item und Flex-Container sein. nav { display: flex; gap: 12px; } ordnet die Links im Menü an, und das Menü selbst ist ein Item der Kopfzeile.

Probier es aus

Logo links, Warenkorb rechts

Bring die Kopfzeile in eine Zeile: das Logo am linken Rand, den Warenkorb am rechten, das Menü dazwischen. Nimm justify-content. Die Prüfung misst, in wie vielen Zeilen die Kinder von <header> stehen.

HTML, CSS, JS

Probier es aus

Finde den Fehler

Die Kopfzeile steht in einer Reihe, aber der Warenkorb rutscht nicht nach rechts. Warum?

Wähle die Zeile mit dem Fehler.

Die Idee

Der freie Platz

In der Kopfzeile gibt es auch ein Suchfeld. Es soll den ganzen Platz zwischen Logo und Warenkorb nehmen, egal wie breit der Bildschirm ist. Dabei helfen drei Eigenschaften des Flex-Items:

  • flex-basis ist die Basis: die Breite des Items, bevor irgendetwas verteilt wird. Standardmäßig ist sie auto: seine width oder so breit wie sein Inhalt.
  • flex-grow sagt, wie viele Teile des freien Platzes sich das Item nimmt. Standardmäßig ist es 0: Es wächst nicht.
  • flex-shrink sagt, wie stark es schrumpft, wenn der Platz nicht reicht. Standardmäßig ist es 1.

Der Browser rechnet so:

  1. Er setzt jedes Item mit seiner Basis.
  2. Der freie Platz ist die Breite des Containers minus die Basen und die gaps.
  3. Er verteilt den freien Platz nach flex-grow, und jedes Item wächst um seinen Anteil.

Die Eigenschaft flex setzt alle drei auf einmal. flex: 1 ist flex-grow: 1, flex-shrink: 1 und flex-basis: 0%: Das Item wächst, und seine Basis ist null. Deshalb werden drei Items mit flex: 1 gleich breit, egal welcher Text darin steht.

Sieh es dir an

So wird der Platz verteilt

Ein 600px breiter Balken mit drei Items. Achte auf die Summe oben und den grünen freien Platz.

.bar {
display: flex;
width: 600px;
gap: 20px;
}
.logo { flex-basis: 120px; }
.search { flex-basis: 100px; flex-grow: 2; }
.cart { flex-basis: 100px; flex-grow: 1; }
Schritt für Schritt, in Worten
  1. .bar ist ein Flex-Container, 600px breit. Seine Kinder sind Flex-Items: Sie stehen entlang der Hauptachse in einer Reihe, von links nach rechts.
  2. Zuerst bekommt jedes Item seine flex-basis: 120, 100 und 100px. Das ist seine Breite, bevor irgendetwas verteilt wird.
  3. Zwischen drei Items liegen zwei gap von je 20px. Belegt sind 120 + 100 + 100 + 2 × 20 = 360px.
  4. Was übrig bleibt, ist der freie Platz: 600 − 360 = 240px.
  5. flex-grow sagt, wie viele Teile sich jedes Item nimmt: logo 0, search 2, cart 1, zusammen drei. Ein Teil sind 240 : 3 = 80px.
  6. Jedes Item wächst um seine Teile: search um 160px, cart um 80px, logo bleibt, wie es ist. Die Breiten sind 120, 260 und 180px.
  7. 120 + 20 + 260 + 20 + 180 = 600: Die Reihe ist voll. Der Browser gibt genau diese Breiten. search ist nicht doppelt so breit wie cart: Nur der freie Platz wird im Verhältnis 2 : 1 verteilt.

search hat flex-grow: 2 und cart hat 1, aber search ist nicht doppelt so breit: 260 gegen 180. Verteilt wird nur der freie Platz, die Basen bleiben. Wenn du gleich breite Spalten willst, muss die Basis also null sein: flex: 1.

Probier es aus

Die Suche nimmt den Rest

Das Logo ist 120px breit, der Warenkorb 110px, und die Kopfzeile ist bis zu 640px breit. Lass das Suchfeld den ganzen Platz dazwischen nehmen. Die Prüfung misst seine Breite in Pixeln: 640 − 2 × 16 (padding) − 120 − 110 − 2 × 16 (gap) = 346px.

HTML, CSS, JS

Probier es aus

Eines nach rechts

Manchmal willst du Logo und Menü links und nur den Warenkorb rechts. space-between geht nicht: Das Menü würde in die Mitte rutschen. Dafür gibt es eine Eigenschaft des Items selbst: Ein margin mit dem Wert auto nimmt den ganzen freien Platz auf seiner Seite und schiebt das Item weg.

header { display: flex; gap: 16px; }
.cart { margin-left: ; }

Probier es aus

Eine neue Zeile, wenn es nicht passt

Standardmäßig hält ein Flex-Container alle Items in einer Zeile (flex-wrap: nowrap). Passen sie nicht, schrumpft er sie, und wenn das nicht mehr geht, ragt die Zeile aus dem Bildschirm. Mit flex-wrap: wrap rutschen die Items, die nicht passen, in eine neue Zeile.

Auf einem Handy (360px) sind die vier Produkte in eine Zeile gequetscht, und die Seite scrollt seitwärts. Setze sie zu zweit in eine Zeile, jedes mindestens 150px breit, und die zwei in einer Zeile gleich breit. Die Prüfung zählt die Zeilen und Spalten und misst die Breite der Karten.

HTML, CSS, JS

Die Idee

Der Name, der nicht schrumpft

Im Warenkorb steht der Name des Produkts neben dem Bild, und daneben stehen Menge und Preis. Der Name ist lang. Wir wollen ihn in einer Zeile mit „…“ abschneiden: white-space: nowrap, overflow: hidden und text-overflow: ellipsis. Der Block mit dem Namen hat flex: 1. Auf einem Handy ragt die Zeile trotzdem aus dem Bildschirm, und der Preis wird gequetscht:

HTML, CSS, JS

Schuld ist eine einzige Regel. Ein Flex-Item schrumpft nicht unter seinen schmalsten Inhalt: min-width ist standardmäßig auto, nicht 0. Für .info ist der schmalste Inhalt der ganze Name in einer Zeile. min-width: 0 am Flex-Item hebt diese Grenze auf. Dann schrumpft .info, und die Überschrift darin schneidet den Text ab.

Jemand hat min-width: 0 ergänzt, aber der Name wird immer noch nicht abgeschnitten. Welche Zeile ist falsch?

Genauer, für Neugierige

Schrumpfen. Ergeben Basen und gaps zusammen mehr als der Container, ist der freie Platz negativ, und die Items schrumpfen. Der Anteil richtet sich nicht nur nach flex-shrink, sondern nach flex-shrink × Basis: Ein breites Item schrumpft stärker. Der Balken aus der Szene, aber nur 280px breit: 120 + 100 + 100 + 40 = 360, es fehlen 80px. Die Gewichte sind 120, 100 und 100. logo verliert 80 × 120 : 320 = 30px, die anderen je 25px: 90, 75 und 75px. Ein Item mit flex-shrink: 0 schrumpft nicht.

Die Werte von flex. flex: 1 ist 1 1 0%. flex: auto ist 1 1 auto: Es wächst, aber von der Breite seines Inhalts aus. flex: none ist 0 0 auto: Es wächst nicht und schrumpft nicht. flex: 0 0 64px ist ein Item von genau 64px.

Was nicht schrumpft. Bilder und Felder haben eine eigene Breite, und min-width: auto hindert sie am Schrumpfen. Deshalb wird im Warenkorb der Preis (<strong>) gequetscht und das Bild nicht.

Ein anderer Weg. Auch overflow: hidden am Flex-Item selbst hebt die Grenze auf: Ein Element, das seinen Inhalt abschneidet, darf bis auf 0 schrumpfen.

Ein Item anders. align-self richtet ein einzelnes Item auf der Querachse aus. order ändert seinen Platz auf dem Bildschirm, aber nicht im Baum: Tastatur und Screenreader folgen dem Baum. Darum verschieben wir mit order nichts, worauf Leute klicken.

Zeilen mit wrap. align-content ordnet die Zeilen selbst auf der Querachse an, wenn der Container höher ist als sie. display: inline-flex macht einen Container, der wie ein Wort im Text steht.

Übung

Eine Zeile im Warenkorb

Ordne eine Zeile des Warenkorbs auf einem Handy (360px) an: Bild, Name, Menge und Preis in einer Reihe, senkrecht zentriert, mit 12px dazwischen. Das Bild bleibt 64px, die Menge 56px, der Preis 72px. Der Name nimmt den Rest des Platzes (hier 108px), steht in einer Zeile und wird, wenn er lang ist, mit „…“ abgeschnitten. Die Seite scrollt nicht seitwärts.

HTML, CSS, JS

Test

Teste dich

1. Du willst drei Produkte nebeneinander. An welches Element schreibst du display: flex?
2. Ein 500px breiter Balken mit gap: 20px hat zwei Items mit flex-basis: 100px. Das erste hat flex-grow: 1, das zweite flex-grow: 3. Wie breit sind sie?
3. Der Container hat flex-direction: column. Entlang welcher Achse wirkt justify-content?
4. Der Name in .info { flex: 1 } hat white-space: nowrap und text-overflow: ellipsis, wird aber nicht abgeschnitten, und die Reihe ragt aus dem Bildschirm. Was fehlt?

Erstellt von Ivo Gergov im Rahmen der Kampagne von Evo Tech für zugängliche Programmierausbildung ·