Flexbox - möge die Macht von CSS mit dir sein

Positionierung von Elementen auf Webseiten war immer ein großes Thema, besonders für Einsteiger ins Webdesign. Aber auch so manch erfahrener Developer kämpft manchmal mit den Elementen, die so ganz und gar nicht dorthin wollen, wo er sie haben will – besonders, wenn die ganze Sache dann auch noch responsiv sein soll.

Glücklicherweise hat CSS dafür ein Ass im Ärmel: die Flexbox. Weil dieses Tool derart mächtig ist, beschäftigen wir uns auch in unseren Kursen eingehend damit.

Flexible Box Module

Mit vollständigem Namen heißt die Flexbox eigentlich Flexible Box Module. Der Name ist Programm: Es handelt sich um ein Modul, das uns ermöglicht, flexibel mit Boxen umzugehen.

Auch vor Flexbox-Zeiten war es natürlich schon möglich, Elemente nebeneinander anzuordnen, beispielsweise mittels der float-property. Dabei entstehen allerdings Probleme, die bei falscher Handhabung dazu führen können, dass uns die Struktur der gesamten Seite zusammenbricht – aber das ist Thema eines anderen Artikels. Die Flexbox ermöglicht uns das Positionieren von Elementen ohne die Schwierigkeiten aller früheren Lösungen – und noch Einiges mehr.

Die bisherigen Lösungsansätze funktionierten so, dass man den inneren Elementen Anweisungen gab, wie sie sich verhalten sollten, also beispielsweise float: left.

Die Flexbox geht den umgekehrten Weg: Wir sagen dem Container, wie sich die Elemente, die sich darin befinden, verhalten sollen.

Für unser Beispiel nehmen wir an, unsere Flexbox ist ein Div mit der Klasse .flex-container, darin liegen mehrere andere Divs mit der Klasse .flex-item. Diese flex-items könnten Text, Bilder, Tabellen oder jeden anderen nur erdenklichen Content enthalten; was wir dort dann hineinpacken, bleibt jedem selbst überlassen – uns interessiert jetzt lediglich das Verhalten der Elemente.




Im Bild oben sehen wir das Standardverhalten, wenn wir mehrere Divs (orange) in einen Container (blau) packen: als Blockelemente ordnen sie sich untereinander an. Damit unser Container zur Flexbox wird, bedarf es einer Anweisung:




Ohne weitere Anweisung ordnen sich die flex-items nun nebeneinander in der Flexbox an:




Im ersten Moment sieht es so aus, als würden sie sich nun so verhalten, als hätte man ihnen die Anweisung float: left gegeben, aber das stimmt so nicht ganz. Zum einen haben wir hier nicht das Problem mit dem übergeordneten Container, wie bei float: left; zum anderen werden die Elemente von der Flexbox erstmal alle in eine Zeile gestopft, solange wir keine weiteren Anweisungen machen. Und das auch, wenn wir eigentlich eine fixe Breite für die flex-items definiert haben.

Hätten wir jetzt nicht drei, sondern zwölf Elemente (zwecks Demonstration unsinnig viele) in der Flexbox, dann werden die flex-items zusammengequetscht, um alle in dieser einen Zeile unterbringen zu können:




Die angegebene Breitenangabe wird ignoriert. Damit Elemente, die nicht mehr in die erste Zeile passen, in die nächste Zeile umspringen dürfen (wie bei float), müssen wir das der Flexbox explizit erlauben:




Die entsprechende Anweisung heißt flex-wrap: wrap; . Damit haben die flex-items wieder ihre zugewiesene Breite und dürfen in die nächste Zeile umspringen:




Soweit waren wir auch schon vor Flexbox-Zeiten. Das würde jetzt dem Verhalten eines korrekt angewendeten float: left entsprechen. Die Flexbox kann aber noch um einiges mehr.

 

Horizontale Aufteilung: justify-content

Wer schon einmal versucht hat, Elemente mittels text-align: center zu zentrieren, hat schon mindestens eine mittelschwere Enttäuschung hinter sich. Das funktioniert natürlich nicht bei Blockelementen. Vielleicht wurde dann mit dem Trick mit margin: 0 auto; gearbeitet? Ja, das funktioniert, aber die Flexbox kann das besser:





Die Eigenschaft justify-content ist für die horizontale Anordnung der Elemente in einer Flexbox zuständig. Dabei gibt es (neben dem Default flex-start, also am Beginn der Flexbox ausgerichtet) noch drei weitere spannende Angaben. Justify-content: center; zentriert die Elemente horizontal:




Das funktioniert für eine oder mehrere Zeilen.

Ein weiterer praktischer Wert ist justify-content: space-between:




Dabei versuchen die Elemente, innerhalb einer Zeile so viel Abstand zueinander zu halten, wie irgend möglich. Das heißt, das erste Element liegt ganz am Anfang der Flexbox, das letzte ganz am Ende, und der in der Zeile noch zur Verfügung stehende Platz wird gleichmäßig als Abstand zwischen den Elementen aufgeteilt. Das „gleichmäßig“ ist hier der entscheidende Punkt: Wir müssen nicht berechnen: wie breit sind meine Elemente? Wie breit kann ich also die Abstände dazwischen machen? Wo muss hier ein margin hin? Links? Rechts? Was mache ich mit dem ersten und letzten Element? All das macht die Flexbox für uns automatisch. Allerdings handelt es sich bei den Abständen in der Flexbox weder um margin noch padding – die Abstände ergeben sich aus dem nach Abzug der Breite der flex-items noch zur Verfügung stehenden Platz.

Es gibt noch einen dritten, sehr hilfreichen Wert, justify-content: space-around:




Hierbei wird der nach Abzug der Breite der flex-items noch zur Verfügung stehende Platz gleichmäßig als Abstand links und rechts von den flex-items aufgeteilt. Daher ist der Abstand zwischen den flex-items doppelt so breit wie der linke Abstand von flex-item 1 und der rechte Abstand von flex-item 3; zwischen flex-item 1 und 2 sowie zwischen 2 und 3 ergibt sich der Abstand aus dem rechten Abstand des ersten und dem linken Abstand des zweiten Elements.

Es gibt noch ein paar weitere Werte, die justify-content zugeordnet werden könnten, aber center, space-around und space-between sind die wichtigsten.

Diese Angaben lassen sich auch problemlos mit einem margin für die flex-items kombinieren; in diesem Fall wäre der margin dann der Mindestabstand, der eingehalten werden muss.

Selbstverständlich kann auch die Flexbox padding und/oder margin bekommen.

 

Vertikale Aufteilung: align-items

Bisher hatte unsere Flexbox noch keine Höhenangabe. Das hat den Vorteil, dass der Container mit dem Inhalt mitwachsen kann. Somit entstehen auch keine Probleme, wenn Elemente in die nächste Zeile springen, weil der viewport kleiner wird (entweder, weil jemand mit dem Browserfenster herumspielt oder weil die Seite auf einem kleineren Ausgabegerät betrachtet wird).

In manchen Fällen werden wir aber einen Container mit einer fixen Höhe haben wollen. Für unser Beispiel weise ich dem flex-container eine Höhe von 300px zu:




Ohne weitere Angaben zur Anordnung der Elemente kleben alle erst einmal in der linken oberen Ecke (also in unserem Fall an flex-start):




Die für die vertikale Aufteilung zuständige Eigenschaft heißt align-items. Die macht natürlich auch nur dann Sinn, wenn die Flexbox eine fixe Höhe hat, ansonsten ist die Flexbox so hoch wie ihr Inhalt und wir haben gar nicht die Möglichkeit, Elemente vertikal auszurichten.

Mit align-items: flex-end bringen wir die flex-items nach unten:




…und mit align-items: center können wir sie vertikal zentrieren:




Das ist eine enorme Erleichterung im Vergleich zu vor-Flexbox-Zeiten: da war es noch ein Kampf mit der Materie, wenn man Elemente vertikal zentrieren wollte, der nicht selten über JavaScript gelöst wurde. Mit der Flexbox brauchen wir lediglich diese eine Anweisung.

Eine spannende Sache lässt sich mit align-items: stretch noch erreichen, wenn die flex-items keine eigene fixe Höhe haben:




Die flex-items erstecken sich dann über die gesamte Höhe der Flexbox.

 

Natürlich lassen sich die Anweisungen für die horizontale und vertikale Ausrichtung miteinander kombinieren:




Mit diesem magischen Zweizeiler erreichen wir eine perfekte Zentrierung unseres Elements/unserer Elemente innerhalb der Flexbox:



Den gleichen Effekt hätte die Anweisung margin: auto innerhalb einer Flexbox.

 

Ausrichtung nach Spalten: flex-direction

Bisher haben wir uns nur um die zeilenweise Anordnung von Elementen gekümmert. Tatsächlich steckt da ein Default-Setting dahinter, nämlich flex-direction: row; .

Wenn unsere Flexbox eine Höhenangabe hat, können wir aber auch für eine Ausrichtung der Elemente in Spalten sorgen:




Beachte, dass mit flex-wrap: wrap das Umspringen in eine neue Spalte erlaubt werden muss – sonst ordnen sich alle in einer einzigen Spalte untereinander an! Die Anweisungen oben ergeben folgendes Bild:




Hier müssen wir natürlich, wie immer bei fix vergebenen Höhen, aufpassen, dass sich alles innerhalb des Containers ausgeht. Diese flex-items sind 110px hoch, somit passen zwei wunderbar in eine Spalte eines 300px hohen Containers.

Das sind die wichtigsten Anweisungen, die man braucht, um eine Flexbox gut strukturieren zu können. Es gibt noch ein paar weitere Spielereien, die aber etwas seltener vorkommen; so kann man beispielsweise mit flex-direction: row-reverse oder column-reverse für eine andere Anordnung der Elemente sorgen, als sie im Dokumentfluss vorliegt.

Mit einer shorthand-property names flex-flow lassen sich die Eigenschaften flex-direction und flex-wrap kombinieren:

Beispiel: flex-flow: row wrap;

 

Anweisungen an Elemente in der Flexbox

Auch den Elementen innerhalb der Flexbox kann man noch ein paar bestimmte Anweisungen geben; allerdings wird man das in der Praxis nicht allzu häufig brauchen. Daher hier nur ein paar kurze Tipps, was man denn noch so alles mit der Flexbox anstellen kann.

Im Normalfall ordnen sich die Elemente in der Reihenfolge an, wie sie auch im Dokumentfluss vorkommen, und in den meisten Fällen wollen wir das auch so. Es hat ja schließlich seinen Grund, warum wir sie so angeordnet haben.

Diese Reihenfolge lässt sich aber auch über CSS verändern. Bleiben wir beim schon verwendeten Beispiel von eben (die Elemente sind in Spalten angeordnet), aber die sechs Elemente in der Flexbox bekommen jetzt jedes auch noch eine Id (#no1 – 6). Über die Id können wir jetzt jedes Element gesondert ansprechen und ihm eine andere Position in der Reihenfolge zuweisen (das wäre übrigens auch über .flex-item:nth-child(x) möglich, wenn wir uns die IDs sparen wollen):






Jedem dieser Elemente wurde mittels order eine neue Position zugewiesen (z.B. order: 2). Dabei zu beachten: gezählt wird wie in einem Array beginnend mit der Stelle 0! Das flex-item 5 befindet sich also an der Stelle 0 (order: 0;), das flex-item 4 an der Stelle 5 (order: 5;).

Das funktioniert genauso für eine Ausrichtung in Zeilen (flex-direction: row; bzw. Defaultwert):




Wenn die flex-items keine fixe Breite haben, sondern sich gleichmäßig über die Zeile ausbreiten sollen, kann man auch noch bestimmen, in welchem Verhältnis sie sich ausbreiten (oder schrumpfen) dürfen. Dafür gibt es die Eigenschaften flex-grow und flex-shrink. Flex-grow bedeutet, dass ein Element, dem flex-grow: 3; vergeben wurde, sich dreimal so breit machen darf wie die anderen, die ein flex-grow: 1; erhalten haben:




Mit flex-shrink verhält es sich umgekehrt: Es bestimmt, in welchem Verhältnis zueinander Elemente schrumpfen sollen, wenn es sich in der Zeile nicht mehr ausgeht.

Dafür gibt es auch noch eine shorthand-property: Mit flex: können wir flex-grow und flex-shrink zusammenfassen. Der Default ist flex: 0 1; .

 

Viel Spaß beim Herumprobieren! Und vielleicht sehen wir uns ja in einem ppedv-Kurs zum Thema HTML und CSS!







Kommentare sind geschlossen