Abschnitt 11 · Lektion 2
Zentrieren
Auf „Wie zentriere ich das?“ gibt es in CSS fünf richtige Antworten. Welche passt, hängt davon ab, was in die Mitte soll.
Vier Wege, die du dauernd brauchst
<p class="titel">1. margin-inline: auto, braucht eine Breite</p>
<div class="feld">
<div class="kasten weg-a">margin-inline</div>
</div>
<p class="titel">2. text-align: center, zentriert den Inhalt</p>
<div class="feld weg-b">
<span>text-align</span>
</div>
<p class="titel">3. Flexbox, zentriert die Kinder in beide Richtungen</p>
<div class="feld hoch weg-c">
<div class="kasten">Flexbox</div>
</div>
<p class="titel">4. Grid mit place-items, dasselbe in zwei Zeilen</p>
<div class="feld hoch weg-d">
<div class="kasten">Grid</div>
</div> *,
*::before,
*::after {
box-sizing: border-box;
}
body {
font-family: system-ui, sans-serif;
}
.titel {
margin-bottom: 4px;
font-size: 14px;
color: #52525b;
}
.feld {
margin-bottom: 16px;
padding: 8px;
background-color: #e4e4e7;
}
.hoch {
height: 120px;
}
.kasten {
padding: 16px 24px;
font-weight: 700;
color: #ffffff;
background-color: #2563eb;
}
/* Eine Breite ist Pflicht. Ohne sie füllt der Block
die ganze Zeile, und dann gibt es nichts mehr zu
verteilen. Wirkt nur waagerecht. */
.weg-a {
width: 220px;
margin-inline: auto;
}
/* Zentriert den Inline-Inhalt, nicht den Kasten
selbst. Vererbt sich nach unten. */
.weg-b {
text-align: center;
}
.weg-c {
display: flex;
justify-content: center;
align-items: center;
}
.weg-d {
display: grid;
place-items: center;
} margin-inline: auto verteilt den übrigen Platz links und rechts gleichmäßig. Dafür braucht der Block zwingend eine Breite, sonst füllt er die ganze Zeile, und es gibt nichts zu verteilen. Außerdem wirkt es nur waagerecht. Das ist der Weg für den zentrierten Inhaltsbereich einer Seite, den du in Lektion 4.3 schon gebaut hast.
text-align: center zentriert den Inline-Inhalt eines Elements, also Text, Bilder und Inline-Blöcke. Nicht das Element selbst. Es vererbt sich, und das ist praktisch und überrascht einen trotzdem gern.
Flexbox mit justify-content: center und align-items: center zentriert die Kinder in beide Richtungen. Zwei Zeilen plus display: flex.
Grid mit place-items: center macht dasselbe in einer Zeile plus display: grid. Für “ein Element mittig in einem Kasten” ist das der kürzeste Weg, den CSS zu bieten hat.
In einem Flex- oder Grid-Container zentriert auch margin: auto am Kind selbst, und zwar in beide Richtungen, denn der automatische Außenabstand schluckt dort den freien Platz auf allen vier Seiten zu gleichen Teilen.
Im Inspector sieht man, wie verschieden die vier Wege vorgehen. Am blauen Kasten des ersten steht bei der Breite, mit der die Spalte startet, margin: 0px 64px. Das auto bleibt dort nicht als Anweisung stehen, im Streifen steht das Ergebnis der Rechnung. Am zweiten Feld steht text-align: center und sonst nichts. Beim dritten kommen justify-content: center und align-items: center dazu, beim vierten align-items: center und justify-items: center. place-items selbst taucht dort nicht auf, nur die beiden Zeilen, in die es zerfällt. Ein paar Shorthands wie margin und padding setzt der Streifen selbst wieder zusammen, place-items gehört nicht dazu.
text-align rückt den Text, nicht den Kasten
<p class="titel">text-align am Elternteil: der Text rückt, der Kasten nicht</p>
<div class="feld text">
<div class="kasten">Ich bin ein Block mit 220px Breite.</div>
</div>
<p class="titel">margin-inline: auto am Kasten: der Kasten rückt</p>
<div class="feld">
<div class="kasten mitte">Ich bin ein Block mit 220px Breite.</div>
</div> *,
*::before,
*::after {
box-sizing: border-box;
}
body {
font-family: system-ui, sans-serif;
}
.titel {
margin-bottom: 4px;
font-size: 14px;
color: #52525b;
}
.feld {
margin-bottom: 16px;
padding: 8px;
background-color: #e4e4e7;
}
.kasten {
width: 220px;
padding: 16px;
color: #ffffff;
background-color: #2563eb;
}
/* Der blaue Kasten klebt weiterhin links, nur seine
Zeilen sind mittig. Das ist der häufigste Irrtum
beim Zentrieren. */
.text {
text-align: center;
}
.mitte {
margin-inline: auto;
} text-align: center am Elternteil, und der Kasten klebt trotzdem links. Mehr verspricht die Eigenschaft auch nicht. Sie zentriert den Inhalt und nicht den Kasten.
Ein Block nimmt die Breite, die er hat, und text-align sagt nur, wie seine Zeilen darin ausgerichtet sind. Willst du den Block selbst bewegen, brauchst du margin-inline: auto an ihm oder einen Elternteil, der ihn ausrichtet.
Bis auf ihre Stelle sind die beiden blauen Kästen gleich, und im Inspector sieht man das genauer als mit bloßem Auge. Beide messen 220 × 70, beide haben dieselbe Schrift, dieselbe Farbe und dasselbe Polster. Auseinander gehen zwei Zeilen. Oben steht margin: 0px, unten margin: 0px 64px. Und am oberen Kasten steht text-align: center, obwohl in seiner eigenen Regel nichts davon vorkommt. Die Angabe kommt vom Elternteil und wird vererbt. Sie richtet die Zeilen im Kasten aus und lässt den Kasten selbst in Ruhe, und darin liegt der ganze Irrtum.
Die Frage ist jedes Mal, ob das Element rücken soll oder sein Inhalt. Aus der Antwort ergibt sich der Weg von allein.
Wenn der Elternteil nicht mitspielt
<div class="feld">
<div class="schild">inset: 0 plus margin: auto</div>
</div>
<p class="hinweis">
Der Elternteil ist hier weder Flex noch Grid, er ist nur
Bezugsrahmen. Das reicht: alle vier Seiten auf null spannen den
verfügbaren Platz auf, und margin: auto verteilt ihn gleichmäßig
in beide Richtungen. Eine Größe braucht das Schild dafür, hier sind
es 280 mal 48 Pixel.
</p> *,
*::before,
*::after {
box-sizing: border-box;
}
body {
font-family: system-ui, sans-serif;
}
.feld {
position: relative;
height: 160px;
margin-bottom: 16px;
background-color: #e4e4e7;
}
.schild {
position: absolute;
inset: 0;
width: 280px;
height: 48px;
margin: auto;
padding: 16px;
text-align: center;
font-weight: 700;
color: #ffffff;
background-color: #2563eb;
}
.hinweis {
max-width: 56ch;
color: #52525b;
} Der fünfte Weg kommt aus Abschnitt 8, mit position: absolute, inset: 0 und margin: auto. Die vier Seiten auf null spannen den verfügbaren Platz auf, und der automatische Außenabstand verteilt ihn gleichmäßig in beide Richtungen.
Am Schild steht im Streifen position: absolute und margin: 56px 42px, und beide Zahlen kannst du nachrechnen. Das Feld ist 160 Pixel hoch, das Schild 48, macht 112 übrig und 56 je Seite. Waagerecht hängt die zweite Zahl an der Breite der Spalte, und bei 364 Pixeln Feldbreite und 280 Pixeln Schild sind es 42. Wird die Spalte breiter oder schmaler, wandert diese Zahl mit. Die 56 bleiben stehen.
Dieser Weg ist selten die erste Wahl, weil er einen Bezugsrahmen und eine Größe am Element braucht. Seit Herbst 2025 geht es auch ohne Größe, denn zusammen mit inset: 0 wirken justify-self: center und align-self: center inzwischen auch an einem absolut positionierten Element, in Safari als letztem seit Version 26. Dafür muss der Elternteil hier gar nichts tun, und das kann keiner der anderen Wege. Kommst du an das Layout des Elternteils nicht heran, etwa weil es aus einer fremden Komponente stammt, ist das der Ausweg.
Bleibt die alte Transform-Lösung, die man in älteren Antworten überall findet.
position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
Die funktioniert weiterhin. Anders als die inset-Variante mit margin: auto muss sie die Größe des Elements nicht kennen. Für die meisten Fälle sind Flexbox und Grid trotzdem kürzer und lesbarer. Ich nehme die Transform-Lösung nur noch, wenn nichts anderes geht.
In der Aufgabe stehen drei Kästen, und jeder will auf einem anderen Weg in die Mitte.
Zum Mitnehmen
Flexbox und Grid zentrieren Kinder in beide Richtungen, margin-inline: auto rückt einen Block mit Breite, text-align rückt nur den Inhalt.
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.