CSS: Layout
CSS Flexbox: Layout entlang einer Achse
Flexbox ordnet Elemente entlang einer einzigen Achse an und verteilt den freien Platz zwischen ihnen. display: flex erzeugt den Container, flex-direction bestimmt die Hauptachse, justify-content verteilt darauf und align-items richtet auf der Querachse aus.
Flexbox löst die Aufgabe, für die vor 2015 float und inline-block herhalten mussten. Ein Container verteilt seine direkten Kinder auf einer Achse und gleicht den Restplatz aus. Die Grundlage ist das CSS Flexible Box Layout Module Level 1 des W3C. Stand September 2026 arbeitest du damit ohne Herstellerpräfixe und ohne Fallback.
Diese Seite gehört zur CSS-Referenz für zugängliche Websites. Sie zeigt das Achsenmodell, jede Eigenschaft mit lauffähigem Beispiel, fünf Muster aus dem Alltag und die Grenze zu CSS Grid für zweidimensionale Layouts. Ein eigener Abschnitt behandelt die Nebenwirkung, die Flexbox in Prüfberichten auffällig macht. Die sichtbare Reihenfolge kann vom Quelltext abweichen.
Das Wichtigste in Kürze
- Flexbox arbeitet auf einer Achse.
flex-directionlegt die Hauptachse fest, und die Querachse steht senkrecht dazu. -
justify-contentwirkt auf der Hauptachse,align-itemsauf der Querachse. Wer die beiden verwechselt, hat meist einflex-direction: columnübersehen. -
flex: 1 1 autoist die brauchbare Voreinstellung für mitwachsende Elemente. Sie erlaubt Wachsen und Schrumpfen und startet bei der Inhaltsgröße. -
gapersetzt Abstände über Margins. Es lässt die Außenkanten frei und funktioniert auch dann, wenn die Items umbrechen. -
orderund die reverse-Werte ändern die Anzeige. Tastatur und Screenreader folgen weiterhin dem Quelltext. Das verstößt gegen 1.3.2 Bedeutungstragende Reihenfolge. - Eine Achse gehört zu Flexbox, zwei Achsen gehören zu Grid. Bei Flexbox bestimmt der Inhalt das Layout. Bei Grid bestimmt das Layout den Platz.
CSS-Flexbox-Layout: Hauptachse und Querachse
Jeder Flex-Container hat zwei Achsen. Die Hauptachse ist die Richtung, in der die Items aufgereiht werden. Die Querachse steht senkrecht dazu. Alle weiteren Eigenschaften beziehen sich auf diese Achsen.
<ul class="werkzeugleiste">
<li><button type="button">Speichern</button></li>
<li><button type="button">Teilen</button></li>
<li><button type="button">Löschen</button></li>
</ul>
.werkzeugleiste {
display: flex;
gap: 1rem;
list-style: none;
margin: 0;
padding: 0;
}
display: flex wirkt nur auf die direkten Kinder des Containers. Die <li>-Elemente werden zu Flex-Items, und ihre Inhalte folgen weiterhin dem normalen Fluss. Die Liste bleibt dabei eine Liste. Wie du Listen richtig auszeichnest, ändert sich durch Flexbox in keinem Punkt.
display: flex und display: inline-flex
display: flex erzeugt einen Container, der sich nach außen wie ein Block verhält. display: inline-flex lässt ihn im Textfluss stehen. Nach innen sind beide identisch.
flex-direction bestimmt die Hauptachse
.zeile { display: flex; flex-direction: row; } /* Voreinstellung */
.spalte { display: flex; flex-direction: column; }
Bei row läuft die Hauptachse in Leserichtung, in einem Dokument mit dir="rtl" also von rechts nach links. Bei column läuft sie von oben nach unten, und die Querachse liegt waagerecht. Die Werte row-reverse und column-reverse drehen die Anzeigerichtung um. Ihre Nebenwirkung auf die Bedienung steht im Abschnitt zur Barrierefreiheit.
Ausrichtung: justify-content gegen align-items
Beide Eigenschaften richten aus. Sie tun es auf unterschiedlichen Achsen.
| Eigenschaft | Achse | Werte | Wirkung |
|---|---|---|---|
justify-content |
Hauptachse, also die Richtung von flex-direction |
flex-start (Voreinstellung), flex-end, center, space-between, space-around, space-evenly |
verteilt den freien Platz zwischen und um die Items |
align-items |
Querachse, also senkrecht zur Hauptachse | stretch (Voreinstellung), flex-start, flex-end, center, baseline |
richtet jedes Item quer zur Laufrichtung aus |
Bei flex-direction: column tauschen beide ihre sichtbare Richtung. Darauf geht die häufigste Verwechslung in Flexbox zurück.
.kopf {
display: flex;
justify-content: space-between;
align-items: center;
min-height: 4rem;
}
Das erste Item steht damit links und das letzte rechts. Alle Items sitzen senkrecht in der Mitte.
align-self für ein einzelnes Element
align-self überschreibt align-items für ein einzelnes Item. Der Standardwert auto übernimmt die Vorgabe des Containers.
.leiste {
display: flex;
align-items: center;
gap: 1rem;
}
.leiste .logo {
align-self: flex-start;
}
align-content für mehrere Zeilen
align-content richtet die Zeilen eines umgebrochenen Containers zueinander aus. Es braucht flex-wrap: wrap, mehr als eine Zeile und freien Platz auf der Querachse.
.galerie {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
gap: 1rem;
min-height: 30rem;
}
Ohne diese Angabe verteilt der Voreinstellungswert stretch die Zeilen über die volle Höhe. align-items richtet weiterhin innerhalb jeder Zeile aus.
flex-wrap und gap
Ein Flex-Container hält seine Items standardmäßig in einer Zeile und drückt sie zusammen. flex-wrap: wrap erlaubt den Umbruch. gap setzt den Abstand zwischen den Items und lässt die Außenkanten frei.
/* Don't: Abstand über Margins mit Ausnahme für das letzte Element */
.karte { width: 32%; margin-right: 2%; }
.karte:last-child { margin-right: 0; }
/* Do: gap regelt den Abstand, flex regelt die Breite */
.karten { display: flex; flex-wrap: wrap; gap: 2rem; }
.karten > .karte { flex: 1 1 18rem; }
Die Margin-Variante fällt aus, sobald die Items umbrechen. gap funktioniert in Flexbox seit 2021 in allen aktuellen Browsern. Stand September 2026 brauchst du dafür weder einen Fallback noch eine :last-child-Regel.
Auto-Margins verteilen freien Platz gezielt
Ein margin mit dem Wert auto schluckt den gesamten freien Platz in dieser Richtung, bevor justify-content zum Zug kommt.
.navigation {
display: flex;
gap: 1rem;
}
.navigation .login {
margin-left: auto;
}
Der Login-Punkt sitzt damit am rechten Rand. Ein margin: auto auf einem einzelnen Item zentriert es auf beiden Achsen. Das ist der kürzeste Weg zur zentrierten Box mit CSS.
Die Kurzform flex: grow, shrink und basis
flex fasst drei Eigenschaften zusammen. flex-grow bestimmt den Anteil am freien Platz. flex-shrink bestimmt, wie stark ein Item bei Platzmangel schrumpft. flex-basis ist die Ausgangsgröße vor der Verteilung.
.spalte {
flex: 1 1 auto; /* flex-grow flex-shrink flex-basis */
}
Die Empfehlung für den Alltag ist flex: 1 1 auto. Das Item wächst, es schrumpft, und es startet bei seiner Inhaltsgröße. Die Kurzform flex: 1 bedeutet dagegen 1 1 0%. Damit ignoriert der Browser die Inhaltsgröße und verteilt den Platz gleichmäßig. Drei Spalten mit unterschiedlich langem Text werden dann gleich breit.
| Kurzform | Bedeutung | Verhalten |
|---|---|---|
flex: 1 1 auto |
wächst, schrumpft, startet beim Inhalt | Breite folgt Inhalt und Restplatz |
flex: 1 |
entspricht 1 1 0% |
alle Items werden gleich breit |
flex: 0 0 auto |
starr | Item behält seine Inhaltsgröße |
flex: 1 1 20rem |
Wunschbreite 20 rem | umbrechende Karten |
Ein Icon oder ein Avatar bekommt flex: 0 0 auto. Ein Item mit langem Inhalt bekommt zusätzlich min-width: 0.
order und warum es gefährlich ist
order verschiebt Items in der Anzeige. Der Standardwert ist 0. Ein Item mit order: -1 rutscht nach vorn, eines mit order: 2 nach hinten.
/* Der Quelltext sagt A, B, C. Die Anzeige sagt C, A, B. */
.spalte-rechts { order: -1; }
Die Reihenfolge im DOM ändert sich dabei in keinem Punkt. Tastatur und Screenreader folgen weiterhin dem Quelltext. Die verlässliche Lösung ist eine korrekte Reihenfolge im HTML-Quelltext mit sauberer Struktur und ein Layout, das dieser Reihenfolge folgt.
CSS-Flexbox-Beispiele: fünf Muster aus der Praxis
Die folgenden Beispiele sind vollständig. Du kannst sie kopieren, das CSS wie gewohnt einbinden und im Browser öffnen. Die Klassen triffst du mit den üblichen CSS-Selektoren.
Navigationsleiste
<nav aria-label="Hauptnavigation">
<ul class="hauptnav">
<li><a href="/">Start</a></li>
<li><a href="/leistungen/">Leistungen</a></li>
<li><a href="/kontakt/">Kontakt</a></li>
<li class="rechts"><a href="/login/">Anmelden</a></li>
</ul>
</nav>
.hauptnav {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.5rem 1.5rem;
list-style: none;
margin: 0;
padding: 0;
}
.hauptnav .rechts {
margin-left: auto;
}
.hauptnav a {
display: block;
min-height: 24px;
padding: 0.75rem 0.5rem;
}
flex-wrap: wrap hält die Leiste bei starker Vergrößerung lesbar. Das padding am Link erzeugt eine Zielfläche, die auch mit ungenauer Motorik zu treffen ist. Was bei Untermenüs dazukommt, steht unter barrierefreie Menüs und Dropdowns.
Karten-Reihe
<div class="karten">
<article class="karte"><h3>Erste Karte</h3><p>Kurzer Text.</p></article>
<article class="karte"><h3>Zweite Karte</h3><p>Etwas mehr Inhalt.</p></article>
<article class="karte"><h3>Dritte Karte</h3><p>Kurzer Text.</p></article>
</div>
.karten {
display: flex;
flex-wrap: wrap;
gap: 2rem;
}
.karten > .karte {
flex: 1 1 18rem; /* Wunschbreite 18 rem, Umbruch darunter */
min-width: 0;
}
Das ist ein responsives Raster ohne Media Query. Jede Karte will 18 rem breit sein. Sobald der Platz fehlt, rutscht die nächste eine Zeile tiefer. Für klickbare Karten lies vorher, wie klickbare Cards ohne Link-Falle gebaut werden.
Sticky Footer
<body class="seite">
<header>Kopf</header>
<main>Inhalt</main>
<footer>Fuß</footer>
</body>
.seite {
display: flex;
flex-direction: column;
min-height: 100vh;
margin: 0;
}
.seite main {
flex: 1 1 auto;
}
Der Fußbereich sitzt bei wenig Inhalt am unteren Fensterrand und rutscht bei viel Inhalt darunter. Die Landmark-Struktur bleibt erhalten. Das zählt für Landmarks und die Dokument-Outline.
Media-Object
<article class="medien-objekt">
<img src="/bilder/avatar.jpg" alt="" width="64" height="64">
<div class="medien-text">
<h3>Überschrift des Beitrags</h3>
<p>Ein längerer Text, der neben dem Bild steht.</p>
</div>
</article>
.medien-objekt {
display: flex;
gap: 1rem;
align-items: flex-start;
}
.medien-objekt > img {
flex: 0 0 auto;
}
.medien-text {
flex: 1 1 auto;
min-width: 0;
}
Das Bild behält seine Größe. Der Text füllt den Rest. min-width: 0 verhindert, dass eine lange URL die Textspalte über den Container hinaus aufbläht.
Zentrierte Box
.buehne {
display: flex;
justify-content: center;
align-items: center;
min-height: 60vh;
}
Die Höhenangabe ist die Bedingung. Ohne Höhe am Container hat die Querachse keinen Platz zu verteilen. Weitere Wege zur Mitte stehen unter Elemente mit CSS zentrieren.
Cheat Sheet: Flexbox-Eigenschaften auf einen Blick
Ein CSS-Flexbox-Cheat-Sheet beantwortet eine Frage. Gehört die Eigenschaft an den Container oder an das Item?
| Am Container | Am Item |
|---|---|
display: flex oder inline-flex |
flex als Kurzform aus grow, shrink, basis |
flex-direction |
align-self |
flex-wrap |
order |
justify-content |
margin: auto für den Restplatz |
align-items und align-content |
min-width: 0 gegen Überlauf |
gap, row-gap, column-gap |
flex-shrink: 0 für starre Elemente |
Flexbox oder Grid: was wann?
Die Regel ist kurz. Flexbox ist für eine Achse zuständig. Grid übernimmt zwei Achsen. Sobald Elemente in Zeilen und Spalten stehen sollen, die zueinander ausgerichtet sind, gehört die Aufgabe zu Grid.
Der zweite Unterschied liegt in der Richtung der Entscheidung. Bei Flexbox bestimmt der Inhalt das Layout: Jedes Item bringt seine Größe mit, und der Container verteilt den Rest. Bei Grid bestimmt das Layout den Inhalt: Du definierst Spuren, und die Elemente setzen sich hinein.
- Eine Navigationsleiste, eine Button-Gruppe oder ein Media-Object baust du mit Flexbox.
- Ein Seitenraster aus Kopf, Seitenleiste, Inhalt und Fußbereich gehört zu Grid.
- Eine Karten-Reihe, die bei Platzmangel umbrechen soll, löst Flexbox.
- Eine Galerie mit gleich breiten und gleich hohen Karten löst Grid.
Beide Systeme ergänzen sich. Ein Grid für die Seite und Flexbox innerhalb der Bereiche ist der Normalfall. Die Details zu Spuren und grid-template-areas stehen unter CSS Grid mit Zeilen und Spalten. Für den Container selbst gilt: Wo eine Landmark, eine Liste oder ein <article> passt, nimm dieses Element. Nur für reine Layout-Zwecke bleibt das <div> richtig, wie der Beitrag Div-Suppe vermeiden zeigt.
Barrierefreiheit: worauf es ankommt
Flexbox verändert die Anzeige. Die Reihenfolge im DOM bleibt unberührt. Daraus entstehen die Befunde, die in Prüfberichten zu Flex-Layouts auftauchen.
order und die reverse-Werte trennen Sehen von Bedienen
order, row-reverse und column-reverse ändern, in welcher Reihenfolge sehende Menschen die Inhalte wahrnehmen. Die Tastatur folgt weiterhin dem Quelltext, und ein Screenreader liest ebenfalls den Quelltext vor. Wer per Tabulatortaste durch eine so sortierte Leiste geht, springt für das Auge scheinbar wild hin und her.
Das verletzt zwei Kriterien der Stufe A. 1.3.2 Bedeutungstragende Reihenfolge verlangt, dass die Lesereihenfolge programmatisch bestimmbar ist, sobald sie für das Verständnis zählt. 2.4.3 Fokus-Reihenfolge verlangt, dass die Fokusreihenfolge Bedeutung und Bedienbarkeit erhält. Ergänzend fordert 2.1.1 Tastatur die Bedienbarkeit ohne Maus.
/* Don't: die Anzeige widerspricht dem Quelltext */
.formular .absenden { order: -1; }
/* Do: die Reihenfolge steht im HTML, das Layout folgt ihr */
.formular { display: flex; flex-direction: column; }
Ein vertretbarer Rest bleibt. order ist brauchbar, wenn die verschobenen Elemente untereinander keine inhaltliche Reihenfolge haben. Prüfe jeden Einsatz mit der Tabulatortaste. Wie das geht, steht unter Tastaturbedienung und sichtbarem Fokus und in der Anleitung zum Selbst-Testen.
flex-wrap ist die Bedingung für Zoom und Reflow
1.4.10 Reflow verlangt, dass Inhalt bei 320 CSS-Pixel Breite ohne waagerechtes Scrollen lesbar bleibt. Das entspricht 400 Prozent Zoom auf einem 1280 Pixel breiten Fenster. Ein Flex-Container ohne flex-wrap presst seine Items dabei in eine Zeile, bis der Text unlesbar wird. Setze flex-wrap: wrap überall dort, wo mehr als zwei Items nebeneinander stehen. Den Prüfweg beschreibt Reflow, Zoom und Textabstände, die Nutzersicht die Seite zur Bildschirmvergrößerung.
gap statt Margin-Hacks
Abstände über margin-right und eine :last-child-Ausnahme fallen aus, sobald die Items umbrechen. gap gilt allein zwischen den Items. Das hilft auch bei 1.4.12 Textabstände, weil vergrößerte Zeilen- und Wortabstände die Zwischenräume dann in Ruhe lassen.
Zielgrößen in Navigationsleisten
Eine Flex-Navigation mit knappem padding erzeugt Links, die kaum zu treffen sind. 2.5.8 Zielgröße Minimum fordert 24 mal 24 CSS-Pixel oder ausreichenden Abstand zwischen den Zielen. Der Weg dorthin ist padding am Link selbst plus gap am Container. Ein padding am <li> bleibt wirkungslos, weil die Zielfläche am Link hängt.
min-width: 0 gegen abgeschnittenen Text
Flex-Items haben min-width: auto und schrumpfen deshalb in aller Regel nicht unter ihre Inhaltsgröße. Eine lange URL oder ein Codeblock drückt die Spalte dann über den Container hinaus, und die Seite bekommt waagerechtes Scrollen. min-width: 0 am Item hebt diese Sperre auf. Was danach mit dem überstehenden Inhalt passiert, regelst du mit overflow und scrollbaren Bereichen.
Häufige Fragen
Was ist der Unterschied zwischen justify-content und align-items?
justify-content verteilt die Items auf der Hauptachse, also in der Richtung, die flex-direction vorgibt. align-items richtet sie auf der Querachse aus, also senkrecht dazu. Bei flex-direction: row wirkt justify-content waagerecht und align-items senkrecht. Bei column ist es umgekehrt. Wenn eine der beiden Eigenschaften wirkungslos scheint, prüfe zuerst die flex-direction.
CSS Flexbox vs Grid: wann nehme ich was?
Flexbox ordnet entlang einer Achse an. Grid arbeitet mit zwei Achsen. Nimm Flexbox für Navigationsleisten, Button-Gruppen und alles, dessen Größe vom Inhalt kommt. Nimm Grid, sobald Zeilen und Spalten aufeinander ausgerichtet sein müssen, etwa bei einem Seitenraster oder einer Galerie mit gleich hohen Karten. Die Kombination ist üblich: Grid für die Seite, Flexbox innerhalb der Bereiche.
Wie funktioniert align-self in CSS Flexbox?
align-self setzt du auf ein einzelnes Flex-Item. Es überschreibt dort den Wert, den align-items am Container vorgibt. Die Werte sind dieselben: flex-start, flex-end, center, baseline und stretch. Der Standardwert auto übernimmt die Vorgabe des Containers. Ein Gegenstück für die Hauptachse fehlt. Dort übernimmt ein margin mit dem Wert auto diese Aufgabe.
Wie schiebe ich ein Element mit auto margins nach rechts?
Setze margin-left: auto auf das Item, das rechts stehen soll. Auto-Margins schlucken in einem Flex-Container den kompletten freien Platz auf der Hauptachse, bevor justify-content ihn verteilt. Das ist der saubere Weg für den Login-Punkt am Ende einer Navigationsleiste. Bei flex-direction: column erledigt margin-top: auto dasselbe nach unten.
Warum wirkt align-content bei mir nicht?
align-content richtet die Zeilen eines Flex-Containers zueinander aus. Es braucht deshalb zwei Voraussetzungen. Der Container hat flex-wrap: wrap und mehr als eine Zeile. Zusätzlich muss auf der Querachse Platz frei sein, den eine Angabe wie height oder min-height liefert. Fehlt eine dieser Bedingungen, bleibt die Eigenschaft ohne sichtbare Wirkung.
Verwandte Themen
- CSS Grid: Layout mit Zeilen und Spalten: das zweidimensionale Gegenstück
- Elemente mit CSS zentrieren: die kurzen Wege zur Mitte
- 1.3.2 Bedeutungstragende Reihenfolge: das Kriterium hinter der Warnung zu
order - Reflow, Zoom und Textabstände: Layouts bei 400 Prozent Zoom prüfen
- Semantik, Barrierefreiheit, SEO und Performance: warum die Quelltext-Reihenfolge auch für Suchmaschinen zählt
Quellen
- CSS Flexible Box Layout Module Level 1: Achsenmodell,
flex-Kurzform und Auto-Margins (W3C) - Grundlegende Konzepte von Flexbox: Referenz zu Container und Item (MDN Web Docs)
- Understanding SC 1.3.2: Meaningful Sequence: die Anforderung an die Lesereihenfolge (W3C WAI)