Flexbox
Flexbox ist eine moderne und einfache Möglichkeit, responsive und flexible Layouts zu erstellen, ohne feste Größenangaben und weitere CSS-Einstellungen wie position, float oder clear nutzen zu müssen.[1][2]
- Einstieg in Flexbox

- Container und Flex-Items
- Flex-Items formatieren
- Ausrichtung von Flex-Items
- Fixer Footer
- Responsives Mehrspaltenlayout
- Mobile first
- aside-Boxen am Rand
Inhaltsverzeichnis
Vorüberlegungen
HTML ist an sich eigentlich schon responsiv. Block-Elemente nehmen von sich aus im Standardwert display: block die volle Breite der Webseite ein und ziehen sich auf schmalen Viewports zusammen. Überstehender Inhalt wird umgebrochen und in einer neuen Zeile dargestellt. Die Probleme beginnen, wenn Elemente nebeneinander dargestellt werden sollen.
Von der Unmöglichkeit pixelgenauer Layouts
Der Versuch pixelgenaue Layouts zu erstellen, indem Breiten, Randstärken und Abstände zusammengerechnet wurden, war auch früher schon nahezu unmöglich und wurde durch den Box-Model-Fehler des Internet Explorers weiter verkompliziert.
Auch wenn es möglich ist, mit media queries unterschiedliche Viewportbreiten abzufragen, gibt es keine idealen, allgemeingültigen Breakpoints. Heutzutage gehen die meisten Nutzer mit mobilen Geräten mit allen möglichen Abmessungen ins Internet.
Für welche Geräte muss ich wann Breakpoints setzen?
So oder ähnlich lauten viele Fragen im Forum. Die Antwort darauf lautet: "Gar nicht!"
Derzeit aktuelle Geräteauflösungen können morgen schon überholt sein. Richte die Breakpoints am Inhalt aus:
- Überlege dir, ab wann dieser bei einer bestimmten Viewportbreite nicht mehr gut aussieht.
Voila Flexbox!
Hier bietet Flexbox eine Lösung, die gegenüber dem Block Layout des Box-Modells flexibel ist.
Mit Flexbox …
- kann die Fließrichtung frei bestimmt werden
- können Elemente innerhalb einer Zeile oder mittels Umbrüchen in mehreren Zeilen angeordnet werden
- erhalten Elemente flexible Größen, die sich am Viewport ausrichten
- können Elemente abweichend von der Reihenfolge im Markup positioniert werden.
Wenn die Breite des Viewports für ein horizontales Mehrspaltenlayout nicht mehr ausreicht, kann die Richtung der Anordnung per media queries auf eine vertikale Anordnung umgestellt werden.
Einstieg
Grundlage des flexiblen Layouts ist eine Flexbox, auch Flex-Container genannt:
nav {
display: flex;
}
ul {
display: flex;
gap: 1em;
margin-left: 0; /*auto */
}
}
- display: flex bei nav macht die direkten Kinder von nav zu Flex-Elementen. In unserem Beispiel sind das das Logo (<span>) und die Liste (<ul>). Statt untereinander stehen sie nun nebeneinander.
-
display: flexbei <ul> macht auch die Listeneinträge (<li>) zu Flex-Elementen. Die Menüpunkte stehen dadurch ebenfalls neben- statt untereinander.
- gap: 1em fügt zwischen den Menüpunkten einen Abstand ein. Man muss also keine einzelnen Außenabstände (margin) an den Listeneinträgen setzen.
- margin-left: 0 bedeutet: Die Liste bekommt keinen zusätzlichen linken Außenabstand.
Würde man stattdessenmargin-left: autoverwenden, dann würde die Liste den gesamten verfügbaren Platz zwischen Logo und Menü „aufsaugen“. Dadurch rutscht das Menü ganz nach rechts.autoist hier also ein einfacher Trick, um ein Flex-Element an den rechten Rand zu schieben.
Responsives Umschalten mit flex-direction
Wenn unsere nav ul mehr Elemente enthält, ragt der Inhalt über den Viewport hinaus und es entstehen Scrollbalken.
Mit flex-wrap dürfen die Flex-Elemente bei Platzmangel in die nächste Zeile umbrochen werden.
Eleganter ist es, mit flex-direction das gesamte Layout der Navigation zu ändern und die Menüpunkte von einer Zeile auf eine Spalte umzustellen:
ul {
display: flex;
gap: 1em;
margin-inline-start: auto;
}
@container (width < 30rem) {
ul {
flex-direction: column;
}
}
.wrapper {
container-type: inline-size;
resize: horizontal;
overflow: auto;
}
Die <ul> ist eine Flexbox. Dadurch stehen die Listenelemente (<li>) normalerweise nebeneinander in einer Reihe.
Wenn der Container schmaler als 30rem wird, passiert etwas anderes:
-
flex-direction: columnändert die Flex-Richtung - Statt nebeneinander (
row) stehen die Elemente jetzt untereinander (column)
Das funktioniert mit einer Medienabfrage @container, die die Breite des Wrappers abfragt und dann den Wert für flex-direction ändert.
Das Menüelement „Mehr über mich“ benötigt aufgrund seines längeren Textes zwei Zeilen. Dadurch wird dieses <li>-Element höher als die übrigen Menüeinträge.
Bei einer Flexbox mit flex-direction: column werden die Elemente untereinander angeordnet und alle Elemente über die Querachse gestreckt (align-stretch). Dadurch erhalten alle Menüeinträge die gleiche Breite, obwohl ihre Inhalte unterschiedlich lang sind. Dieses Beispiel zeigt, dass die Größe eines Flex-Items nicht nur vom Inhalt, sondern auch von den Flexbox-Eigenschaften beeinflusst wird.
Mit flex-wrap: wrap; werden die Flex-Items in ihrer „normalen“ Breite dargestellt. Flex-Items, die nicht mehr in die Zeile passen, rutschen in die nächste Zeile.
Flex-Container und Flex-Items
Zeit für ein bisschen Theorie: Durch display: flex wird das Elternelement zum flexiblen Container.
Innerhalb eines Flex-Containers werden die direkten Kind-Elemente zu Flex-Items (englisch wörtlich etwa: Ding, Gegenstand, Partikel). Anstelle des sperrigen Ausdrucks flexible Kind-Elemente behalten wir in diesem Tutorial den englischen Ausdruck Flex-Item bei.
Die Flex-Items werden entlang der Hauptachse nebeneinander angeordnet. Die Breite wird vom Browser nach einem Algorithmus berechnet, der das Seitenverhältnis der Boxen berücksichtigt.
Flex-Items formatieren
Nicht nur der umgebende Container, sondern auch die einzelnen Kind-Elemente (engl. flex items) können mit Flexbox formatiert werden.
.flex-container {
nav ul, .flex-container {
display: flex;
gap: 1em;
}
nav li, .flex-item {
flex: auto;
}
Im Beispiel erhalten alle Listenelemente der Navigation und Kind-Elemente innerhalb des flexiblen Containers die CSS-Eigenschaft flex: auto.
So sind nicht nur die Textblöcke unten, sondern auch die li-Elemente in der oberen Reihe nun über die gesamte Breite verteilt. Ihre Breite richtet sich nicht nach irgendeiner CSS-Festlegung, sondern nach dem verfügbaren Platz. Wenn sich der Viewport verändert, verändert sich auch die Breite der Elemente.
Bisher haben wir die Kurzschreibweise
flex: auto;
verwendet. Sie entspricht:
flex: 1 1 auto;
Die drei Werte stehen für:
- flex-grow: Darf ein Flex-Item wachsen, wenn freier Platz vorhanden ist?
- flex-shrink: Darf ein Flex-Item kleiner werden, wenn der Platz nicht ausreicht?
- flex-basis: Welche Ausgangsgröße soll für die Berechnung verwendet werden?
Mit flex: auto dürfen die Flex-Items also wachsen und schrumpfen. Der Browser verwendet dabei die Inhaltsgröße als Ausgangspunkt und verteilt den verfügbaren Platz auf die Flex-Items.
Einer der großen Vorteile der Flexbox ist die einfache Handhabung. Wenn man bisher mehrere Elemente nebeneinander platzieren wollte, musste man (wenn auch einfache) mathematische Rechnungen anstellen, um auf die gewünschten Prozent- oder gar Pixelwerte für Breiten zu kommen. Mit der einfachen Einstellung flex: 1; bekommen alle Elemente die gleiche Breite.
Soll ein Element doppelt so groß werden, ist dies einfach zu bewerkstelligen:
nav ul, .flex-container {
display: flex;
gap: 1em;
}
nav li, .flex-item {
flex: auto;
}
nav li:nth-of-type(2) {
flex-grow: 2;
background: lightyellow;
}
Der zweite Menüpunkt wird mit dem nth-of-type-Selektor ausgewählt und erhält mit flex-grow die doppelte Breite, aber nur wenn der Browser den Platz findet.
Ausrichtung von Flex-Items
Flex-Items können bei festen Größenangaben kleiner als der Flex-Container sein und dann beliebig innerhalb des Flex-Containers ausgerichtet werden.
justify-content - Elemente verteilen
Die Eigenschaft justify-content legt fest, wie die einzelnen flexiblen Elemente entlang der Hauptachse angeordnet werden.
.menu, .flex-container {
display: flex;
gap: 1em;
justify-content: flex-start;
}
nav li, .flex-item {
flex: 0 1 auto;
}
/* interactive control via :has() */
body:has(input[value="center"]:checked) .menu {
justify-content: center;
}
body:has(input[value="space-between"]:checked) .menu {
justify-content: space-between;
}
Die einzelnen Menüpunkte erhalten mit
flex: 0 1 auto:
-
flex-grow: 0: Das Item darf nicht wachsen, es behält die Größe seines Inhalts -
flex-shrink: 1: Es darf aber soweit schrumpfen wie möglich (Standardwert) -
flex-basis: auto: Die Größe basiert auf dem Element selbst.
Dies ist die “natürliche” Größe bevor Flexbox aktiv wird.
Jetzt wird mit dem :has()-Selektor überprüft, welche Checkbox ausgewählt ist und der entsprechende Wert für justify-content verwendet. Der Browser verteilt die Flex-Items nun innerhalb des Flex-Containers.
Vertikale Anordnung mit align-items
Flexbox unterscheidet zwischen Hauptachse (justify-content) und Querachse (align-items). Im Gegensatz zu justify-content geht es hier meist um die vertikale Anordnung, z. B. von Bildern.
.menu {
display: flex;
gap: 1em;
align-items: center;
height: 6rem;
justify-content: flex-start;
}
.flex-container {
display: flex;
gap: 1em;
align-items: flex-start; /* or stretch */
}
nav li, .flex-item {
flex: 0 1 auto;
}
/* interactive control via :has() */
body:has(input[value="center"]:checked) .menu {
align-items: center;
}
body:has(input[value="stretch"]:checked) .menu {
align-items: stretch;
}
Das zweite Listenelement „Viel mehr über mich“ ist länger als die anderen Flex-Items. Wird der Platz knapp, bricht der Text um und das Flex-Item wird schmaler und höher.
Mit align-items kann man die Listenelemente vertikal orientieren.
Information
Diese Eigenschaften sind mittlerweile auch im Grid Layout verfügbar, können dort jedoch teilweise andere Werte annehmen.
Vergleiche:
Mehrzeilige Flexboxen
Die Eigenschaft align-content legt fest, wie die Reihen einer mehrzeiligen Flexbox im Flexbox-Container verteilt werden sollen. In einer einzeiligen Flexbox (flex-wrap: nowrap) ist die Eigenschaft ohne Funktion, die einzige vorhandene Reihe ist immer so groß wie der Container.
.menu {
display: flex;
flex-wrap: wrap;
gap: 1em;
height: 15em;
width: 25em;
}
/* interactive control via :has() */
body:has(input[value="center"]:checked) .menu {
align-content: center;
}
body:has(input[value="space-between"]:checked) .menu {
align-content: space-between;
}
Wir haben nun mehr links in unserer Navigation, die mit flex-wrap: wrap; in mehrere Zeilen umbrechen.
Der Flex-Container erhält zu Demonstrationszwecken eine feste Höhe von 15em. Mit align-content könne sie nun quer zur Hauptachse angeordnet werden.
Für eine Flexbox mit flex-direction: row verlaufen die Flex-Reihen horizontal. Wird flex-direction: column verwendet, verlaufen sie vertikal.
Bei einer mehrzeiligen Flexbox können zwei Arten von freiem Platz entstehen:
- Innerhalb einer Reihe zwischen den Flex-Items.
- Zwischen den Reihen bzw. um die Reihen herum.
Für diese Bereiche gibt es unterschiedliche Eigenschaften:
-
justify-contentverteilt den freien Platz innerhalb einer Reihe entlang der Hauptachse. -
align-itemsrichtet die Flex-Items innerhalb einer Reihe entlang der Querachse aus. -
align-contentverteilt mehrere Reihen entlang der Querachse.
Deshalb wirken align-items und align-content ähnlich, lösen aber unterschiedliche Aufgaben.
Ausnahmen mit align-self
Bisher haben wir alle Flex-Items gemeinsam ausgerichtet. Mit align-self kann ein einzelnes Flex-Item abweichend ausgerichtet werden.
In einer Navigation macht das eher wenig Sinn – in einer Toolbox oder bei Cards aber schon:
section {
display: flex;
justify-content: space-around;
align-items: flex-start;
}
#ausnahme {
align-self: flex-end;
}
Die Reihenfolge mit order ändern
Standardmäßig werden Flex-Items in der Reihenfolge dargestellt, in der sie im HTML-Dokument stehen.
Mit der Eigenschaft order kann die visuelle Reihenfolge geändert werden:
.item1 { order: 2; }
.item2 { order: 1; }
.item3 { order: 3; }
Die Flex-Items werden dann in der Reihenfolge 2, 1, 3 angezeigt.
Dabei wird jedoch nur die Darstellung geändert. Die Reihenfolge im HTML-Dokument bleibt unverändert. Screenreader und die Tastaturnavigation orientieren sich weiterhin an der Quellreihenfolge.
Deshalb sollte order nur in Ausnahmefällen verwendet werden. In den meisten Fällen ist es besser, die gewünschte Reihenfolge bereits im HTML festzulegen.
Ein Anwendungsfall ist der Adventskalender, bei dem die Türchen per Zufall angeordnet werden.
Flexbox oder Grid Layout?
Jeffrey Zeldman empfiehlt den Einsatz von Grid Layout, wenn ein Layoutraster erstellt werden soll, von Flexbox, wenn bestehende Inhalte ein Layout erhalten sollen.[3]
Flexbox is essentially for laying out items in a single dimension – in a row OR a column. Grid is for layout of items in two dimensions – rows AND columns.
„Flexbox dient im Wesentlichen dem Layout von Objekten in einer Zeile oder einer Spalte. Grid ist für ein Layout in zwei Dimensionen - Zeilen und Spalten.“ Rachel Andrew[4]
Flexbox ist nicht per se responsiv, wie das Beispiel 1 auf sehr schmalen Viewports zeigt. Es kann mittels media queries umschalten. Dies kann im Grid Layout bereits mit Mindestgrößen realisiert werden.
→ Grid Layout/Responsive Raster ohne Media Queries
Wenn Flex-Items über mehrere Zeilen umbrechen, hast du immer die gleichen Höhen. Mit Grid kann man Reihen und Spalten freie und variable Größen geben.
→ Grid Layout/Implizite und explizite Erzeugung#feststehender Footer
Weblinks
- ↑ CSSWG: CSS Flexible Box Layout Module Level 1
- ↑ MDN: flexible Boxes: Basic concepts of flexbox (en)
- ↑ Jeffrey Zeldman auf Twitter
- ↑ Rachel Andrew: Should I use Grid or Flexbox?
Demos
- Philip Walton: Solved by Flexbox Showcase von 6 typischen Layout-Beispielen, die mit Flexbox realisiert wurden
- flexboxfroggy – A game for learning CSS flexbox
- Flexbox Patterns
Generatoren
- echoplex.net: Flexy Boxes
- Bennett Feely: Flexplorer
- Flexbox please