Heute beschäftigen wir uns mit einem Thema, das nicht nur Anfänger das eine oder andere Mal ins Boxhorn jagt. Auch Fortgeschrittene oder Profis haben immer mal wieder das Problem, dass sie in Situationen kommen, bei denen selbst sie unsicher sind, wie sich ein bestimmtes Element in einem speziellen Anwendungsfall (am besten) zentrieren lässt.
In diesem Artikel möchte ich zum einen die unterschiedlichen Faktoren vorstellen, die beim Zentrieren eine Rolle spielen und beeinflussen, was funktioniert und was nicht. Im nächsten Schritt spielen wir dann verschiedene Szenarien durch und besprechen, wie man diese lösen könnte. Zum Ende werde ich noch ein kurzes Fazit ziehen.
Warum ist das Zentrieren mit CSS so schwer?
Bevor wir tiefer in das Thema einsteigen, möchte ich aber noch kurz eine Frage beantworten, die vermutlich vielen von euch auf dem Herzen liegt: Warum ist das Zentrieren mit CSS so schwer?
Wenn ihr mich fragt, dann ist es prinzipiell gar nicht so schwer. Eigentlich gibt es in CSS deutlich schwierigere Sachen, mit denen sich ein Webentwickler so rumschlagen muss. Der Grund dafür, dass es zahlreichen Leuten so schwer vorkommt, ist eher die Tatsache, dass besonders beim Zentrieren unzählige Wege nach Rom führen. Durch die vielen unterschiedlichen Faktoren, die beim Zentrieren eine Rolle spielen, gibt es keine allgemeine Lösung, sondern nur situationsabhängige. Was das eine Mal funktioniert, kann beim nächsten Mal der komplett falsche Ansatz sein, da es sich z.B. nicht um Text, sondern ein Bild handelt. Und das ist noch ein sehr einfaches Beispiel.
Diese Faktoren müssen beim Zentrieren mit CSS beachtet werden
Welche Faktoren müssen wir also berücksichtigen, wenn wir ein beliebiges Element mit CSS zentrieren wollen?
Die erste Frage, die wir uns stellen müssen, ist logischerweise “Was soll zentriert werden?”. Im Wesentlichen kann es darauf zwei verschiedene Antworten geben:
- Inline-Elemente (z.B. Links) oder Textzeilen (z.B. Text in Paragraphen oder Überschriften)
- Ein Bild oder ein beliebiges Blockelement (z.B. p, div, header usw.)
Der erste Faktor, den es zu berücksichtigen gilt, ist also der Typ des Elements, das zentriert werden soll. Wenn man diese Frage beantwortet hat, fallen schon mal viele Möglichkeiten weg.
Weiter geht es dann mit der Frage “Wie soll das Element zentriert werden?”. Hier gibt es drei Möglichkeiten: Entweder das Element wird horizontal, vertikal oder sogar horizontal und vertikal zentriert. Auch kommt es vor, dass beispielsweise mehrere Elemente gemeinsam ausgerichtet werden sollen. Dieser Faktor kann in einigen Fällen die Schwierigkeit des Zentrierens erhöhen.
Zuletzt besteht noch die Frage “Welche Maße sind bekannt?”. Dabei geht es vor allen Dingen darum, ob die Breite und/oder Höhe des (Eltern)elements bekannt ist. Dies spielt besonders seit der Entwicklung zum responsiven Webdesign eine große Rolle, da es häufig vorkommt, dass die Breite oder Höhe nicht bekannt ist, was den Schwierigkeitsgrad in manchen Fällen ebenfalls deutlich erhöht.
Nachdem wir die verschiedenen Faktoren kurz angerissen haben, können wir uns nun daran orientieren. Wer die Zusammenhänge der besprochenen Faktoren beim Zentrieren noch nicht ganz verstanden hat, wird nun, wenn es an die konkreten Beispiele geht, noch schlauer werden. Also keine Angst. Vieles ergibt sich von selbst.
Inline-Elemente oder Textzeilen zentrieren
Auf geht’s! Wir beginnen mit der banalsten Form des Zentrierens: Die Zentrierung von Inline-Elementen oder Textzeilen, wie z.B. Text in Paragraphen oder Überschriften.
Horizontale Zentrierung
Zuerst zentrieren wir Text in einem Paragraphen horizontal.
Um dies zu erreichen, greifen wir auf die CSS-Eigenschaft text-align
zurück und setzen diese auf center
. Mehr benötigen wir nicht.
p {
text-align: center;
}
Wichtig anzumerken ist hierbei, dass sich das “Elternelement” (p
)
des Textes selber nicht zentriert und die Höhe oder Breite des Elements
völlig unrelevant ist. Wenn wir zusätzlich noch einen Rahmen vergeben
und die Breite beispielsweise auf 400px einstellen,
wird dies eindeutig sichtbar.
p {
text-align: center;
width: 400px;
border: 1px solid green;
}
Dieses Verhalten ändert sich bei Inline-Elementen.
Dort können wir nämlich ebenfalls mit text-align
eine
Zentrierung erreichen, nur in dem Fall von dem ganzen Element.
Spontan würde sich da z.B. ein Link anbieten. Wieder nutze ich zur Veranschaulichung einen Rahmen und ihr werdet einen deutlichen Unterschied feststellen:
div {
text-align: center;
}
a {
border: 1px solid green;
}
Wichtig: Da wir keinen Text, sondern das Inline-Element zentrieren möchten, müssen wir natürlich dem übergeordneten Element die Eigenschaft zuweisen, nicht dem Inline-Element.
Am besten kann man sich diesen Unterschied mit der Vorstellung merken,
dass Text selber auch ein Element ist und wir immer dem Elternelement
die entsprechende Eigenschaft zur Zentrierung mitgeben müssen.
Beim Link ist also der div
-Container ganz klar das Elternelement,
das die Eigenschaft bekommt. Beim Text ist es der Paragraph,
also das p
-Element, welches das Elternelement ist, schließlich
befindet sich der Text innerhalb des Paragraphen.
Vertikale Zentrierung
Soweit, so gut. Aber wie kann man Text oder Inline-Elemente innerhalb eines Containers vertikal zentrieren?
Hier kommt das erste Mal die Frage nach den Maßen des Containers auf den Tisch. Die Breite des Containers ist erstmal egal, aber was ist mit der Höhe? Diese ist hingegen schon relevant.
Angenommen wir haben einen Container, der 100px hoch ist:
Die Lösung wäre da die Eigenschaft line-height.
Mit dieser kann man die Zeilenhöhe des Textes festlegen und,
weil der Text innerhalb der Zeile immer vertikal zentriert
dargestellt wird, müssen wir die line-height nur an die Größe
des Containers anpassen:
div {
background-color: lightgreen;
height: 100px;
}
p {
line-height: 100px;
}
Das Gleiche funktioniert genauso mit Inline-Elementen, allerdings wird dabei nicht die Höhe des Elements beeinflusst, was bei einem Blockelement hingegen schon passiert.
Das große Problem bei der line-height
-Methode ist,
wenn wir eine prozentuale Höhe beim Container haben.
Wenn der Container nämlich z.B. die Höhe 10% hat und wir dann versuchen,
die line-height
ebenfalls daran anzupassen,
bekommen wir nicht das gewünschte Ergebnis.
Das liegt daran, dass sich eine prozentuale
line-height
-Angabe an der Schriftgröße orientiert.
Was haben wir also für Alternativen? Die beste Variante wäre,
auf die height
-Angabe zu verzichten und die Höhe der
Elemente stattdessen durch den Inhalt bestimmen zu lassen.
In unserem Beispiel durch den Text sowie die Innenabstände.
Das würde unseren Text perfekt vertikal zentrieren:
div {
background-color: lightgreen;
}
p {
padding: 2% 0;
}
Im Falle eines Inline-Elements, das man zentrieren möchte,
müsste man stattdessen dem Elternelement das padding
zuweisen.
Leider gibt es aber auch im responsiven Webdesign immer noch Fälle,
wo eine prozentuale Höhe verwendet wird. Folglich brauchen wir
auch dafür eine Lösung. Ein Ansatz dafür greift auf absolute
Positionierung sowie transform: translateY()
zurück.
Wichtig anzumerken ist dabei, dass zwar der Text letztendlich auch
zentriert ist, aber eigentlich der Paragraph selber zentriert wird.
html, body {
height: 100%;
}
div {
background-color: lightgreen;
height: 10%;
position: relative;
}
p {
position: absolute;
top: 50%;
transform: translateY(-50%);
margin: 0; /* Zurücksetzen des vom Browser vergebenen margins */
}
Bei dieser Variante wird der Paragraph im Grunde bezogen auf den
übergeordneten div
-Container um 50% nach unten “geschoben”,
sodass die obere Kante des p
-Elements genau vertikal
zentriert wird. Da wir aber nicht die obere Kante des Elements,
sondern die vertikale Mitte des Elements zentrieren wollen,
müssen wir mit transform: translateY(-50%)
gegensteuern
und das Element um die Hälfte der Höhe zurück nach oben schieben,
sodass wir die gewünschte vertikale Zentrierung erreichen.
Für Inline-Elemente gilt in dem Fall komplett dasselbe.
Horizontale und vertikale Zentrierung
Nachdem wir uns nun sowohl die horizontale als auch die vertikale Zentrierung für Text und Inline-Elemente angeschaut haben, versuchen wir beides zu kombinieren.
Beginnen wir mit der Variante für feste Höhen, wie z.B. 100px.
Die vertikale Zentrierung hatten wir dabei mit line-height
gelöst und die horizontale mit text-align
.
Genau das können wir jetzt einfach kombinieren:
div {
background-color: lightgreen;
height: 100px;
}
p {
line-height: 100px;
text-align: center;
}
Falls es um die Zentrierung eines Inline-Elements geht,
müssen wir, genau wie zuvor, das text-align
dem
Elternelement und nicht z.B. dem Link zuordnen.
Soweit die erste Variante. Bei der Zweiten der vertikalen
Zentrierung hatten wir mit padding
gearbeitet.
Dies können wir jetzt wieder machen,
kombiniert mit text-align
:
div {
background-color: lightgreen;
}
p {
padding: 2% 0;
text-align: center;
}
Bei einem Inline-Element geht dies wieder genauso,
allerdings bekommt statt dem Element, das zentriert werden soll,
das Elternelement die beiden Eigenschaften
text-align
sowie padding
zugewiesen.
Für den Fall, dass wir mit einer prozentualen Höhe beim Container
arbeiten, greifen wir erneut auf unsere Variante mit absoluter
Positionierung sowie transform: translateY()
zurück.
Da die absolute Positionierung aber dafür sorgt,
dass das p
-Element seine Breite von 100% verliert,
die für jedes Block-Element Standard ist, müssen wir noch zur
Korrektur eine Breite von diesen 100% setzen,
damit das text-align
wieder seinen gewohnten Effekt hat.
html, body {
height: 100%;
}
div {
background-color: lightgreen;
height: 10%;
position: relative;
}
p {
position: absolute;
top: 50%;
transform: translateY(-50%);
margin: 0; /* Zurücksetzen des vom Browser vergebenen margins */
width: 100%;
text-align: center;
border: 1px solid red;
}
Clevere Leser werden wissen, dass dies beim Inline-Element nicht
nötig ist. Hier reicht es aus, die Definition der Eigenschaft
text-align
zum Elternelement zu verschieben,
wie wir es auch schon zuvor bei der einfachen horizontalen
Zentrierung vorgenommen haben.
Ein Bild oder ein beliebiges Block-Element zentrieren
Nun fahren wir mit den Bildern und Block-Elementen fort. Keine Angst, es wird nicht viel schwerer.
Horizontale Zentrierung
Ich würde sagen, wir beginnen mit dem Block-Element. Eine horizontale Zentrierung ist, wie eigentlich immer, relativ einfach.
In den folgenden Beispielen gehen wir von einem div
aus,
den wir innerhalb eines anderen div
-Containers
zentrieren möchten. Unser Mittel zum Zweck ist diesmal die
margin
-Eigenschaft, welche neben Prozent- sowie
Pixelwerten usw. auch das Keyword auto
erlaubt.
Im Prinzip sorgt der Wert auto
dafür, dass der Browser
selbst den Außenabstand festlegt.
Im Anwendungsfall der horizontalen Zentrierung,
kann man sich das insofern zu Nutzen machen,
dass man die Abstände zu den Seiten des Elements,
also nach links und rechts, dem Browser mittels auto
überlässt. Die Folge ist eine perfekte Zentrierung des Block-Elements.
Wichtig ist, dass man dem zu zentrierenden Element eine beliebige
Breite mitgibt, da der Container sonst einfach die volle Breite
einnimmt und es nichts zu zentrieren gibt.
div.parent {
background-color: lightgreen;
}
div.child {
background-color: red;
margin: 0 auto;
width: 800px;
padding: 1%;
}
Schön ist übrigens, dass sich die gleiche Methode auch bei Bildern
einsetzen lässt. Dabei muss lediglich beachtet werden,
dass Bilder keine Block-Elemente, sondern Inline-Block-Elemente sind.
Somit muss zuvor der display
-Typ geändert werden,
denn die Methode mit margin: auto
funktioniert nur bei
Block-Elementen.
div {
background-color: lightgreen;
}
img {
display: block;
margin: 0 auto;
width: 800px;
}
Vertikale Zentrierung
Nun kommen wir zur vertikalen Zentrierung. Hier würden sicher viele
auf die Idee kommen, dass der margin
-Trick ebenfalls
funktioniert. Dies ist aber nicht der Fall, da margin-top
und -bottom
bei dem Wert auto
vom Browser
auf 0 gesetzt werden.
Es hilft also alles nichts. Wir müssen leider eine Alternative finden. Die erste Möglichkeit basiert dabei auf einer festen Höhe des Block-Elements in Pixeln:
div.parent {
background-color: lightgreen;
height: 300px;
position: relative;
}
div.child {
background-color: red;
width: 100%;
height: 100px;
position: absolute;
top: 50%;
margin-top: -50px;
}
Wie bereits früher in diesem Artikel, greifen wir wieder auf absolute
Positionierung zurück. Diesmal nutzen wir allerdings ein negatives
margin
, um den bereits vorhin beschriebenen Ausgleich
zu schaffen, der nötig ist, da sonst lediglich die obere
Kante zentriert wird. Demzufolge muss der negative
margin-top
-Wert natürlich immer genau die Hälfte der
Höhe des Elements betragen, das zentriert werden soll.
Die gleiche Vorgehensweise lässt sich im Grunde wieder auf ein Bild
anwenden und diesmal muss sogar der display
-Typ
nicht geändert werden.
Des Weiteren ist es allgemein empfehlenswert,
transform: translateY(-50%)
dem negativem Margin
vorzuziehen, da diese Methode schlicht und ergreifend “sauberer” und
eleganter ist. Außerdem ist es damit natürlich auch möglich,
Container mit einer unbekannten bzw. prozentualen Höhe
vertikal zu zentrieren:
div.parent {
background-color: lightgreen;
height: 300px;
position: relative;
}
div.child {
background-color: red;
width: 100%;
padding: 1% 0;
position: absolute;
top: 50%;
transform: translateY(-50%);
}
Horizontale und vertikale Zentrierung
Eine Kombinierung von horizontaler und vertikaler Zentrierung ist erneut relativ leicht machbar.
Bei einem Block-Element mit fester Höhe und Breite kann absolute
Positionierung mit dem negativen margin
wie folgt genutzt werden:
div.parent {
background-color: lightgreen;
height: 300px;
position: relative;
}
div.child {
background-color: red;
width: 500px;
height: 200px;
position: absolute;
top: 50%;
left: 50%;
margin: -100px 0 0 -250px;
}
Der Trick ist genau derselbe, nur dass wir diesmal den Container
mit der Eigenschaft left
zusätzlich um 50% nach rechts
verschieben und wieder mit margin-left
dagegenhalten.
Zu beachten gilt beim linken margin
, dass es
selbstverständlich die Hälfte der Breite sein muss.
Auch dies funktioniert natürlich genauso mit einem Bild und
ebenfalls würde ich wiederum dazu raten,
transform: translate()
statt dem negativen
margin
zu verwenden. Wie schon zuvor ermöglicht dies
die Arbeit mit prozentualen Maßen:
div.parent {
background-color: lightgreen;
height: 300px;
position: relative;
}
div.child {
background-color: red;
width: 80%;
height: 70%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
Mehrere Block-Elemente horizontal zentriert in einer Zeile anordnen
Nicht selten kommt es vor, dass nicht nur ein Element zentriert werden soll, sondern z.B. drei. Diese sollen sich dann in einer Reihe bzw. Zeile befinden und horizontal zentriert werden.
Ein Lösungsansatz dafür könnte sein, den Kindelementen den
display
-Typ inline-block
zu verpassen,
sodass diese nebeneinander angeordnet werden und sich zudem durch das
Setzen der Eigenschaft text-align beim Elternelement zentrieren lassen:
div.parent {
background-color: lightgreen;
height: 300px;
text-align: center;
}
div.child {
background-color: red;
display: inline-block;
height: 100%;
width: 30%;
margin-left: 1.5%;
}
div.child:first-child {
margin-left: 0;
}
Dasselbe funktioniert ebenfalls mit einer prozentualen Höhe des
Elternelements, vorausgesetzt das übergeordnete Element des
Elternelements hat eine Höhe gesetzt. Wenn dies nicht der Fall ist,
hat die prozentuale height
-Angabe des Containers nämlich
keinen richtigen Bezugswert.
Mehrere Block-Elemente horizontal und vertikal zentriert in einer Zeile anordnen
Möchte man dies noch ein wenig erweitern und zusätzlich die Container auch vertikal zentrieren, ist dies durch die Kombination mit unserem Wissen zur vertikalen Zentrierung gut möglich. Diesmal verwende ich übrigens prozentuale Werte, damit ihr seht, dass beides funktioniert:
html, body {
height: 100%;
}
div.parent {
background-color: lightgreen;
height: 50%;
text-align: center;
position: relative;
}
div.child {
background-color: red;
display: inline-block;
height: 80%;
width: 30%;
position: relative;
top: 50%;
transform: translateY(-50%);
margin-left: 1.5%;
}
div.child:first-child {
margin-left: 0;
}
Im Grunde handelt es sich dabei um dasselbe Prinzip,
wie im Beispiel zuvor, nur haben wir jetzt die relative
Positionierung und transform: translateY()
hinzugefügt,
um ebenfalls eine vertikale Zentrierung zu erreichen.
Wichtig ist, dass ihr die Kindelemente wirklich auch relativ
positioniert, da sich diese ansonsten nicht mehr im
gewöhnlichen Elementfluss befinden und nicht mehr
nebeneinander angeordnet sind.
Da es im responsiven Design aber heutzutage eher nicht gewünscht ist,
Höhen zu setzen, gibt es ebenfalls eine Möglichkeit,
dem Content die Beeinflussung der Höhen zu überlassen und trotzdem noch
die horizontale und vertikale Zentrierung hinzubekommen.
Die Lösung ist, alle height
-Angaben sowie die Eigenschaften
zur vertikalen Zentrierung komplett zu entfernen und anschließend den
Kindelementen ein vertical-align
von
middle
zuzuweisen:
div.parent {
background-color: lightgreen;
text-align: center;
}
div.child {
background-color: red;
display: inline-block;
width: 30%;
margin-left: 1.5%;
vertical-align: middle;
}
div.child:first-child {
margin-left: 0;
}
div.child p {
margin: 0;
}
Wen es stört, dass die größte Box die gesamte Höhe des Elternelements
einnimmt, kann diesem ein padding
geben.
Ansonsten ist das große Problem im Vergleich zu der Methode mit einer festen Höhe, dass alle drei Container unterschiedliche Höhen haben.
Für die Behebung dieses Problems müsste man auf eine komplett andere
Konstruktion mit dem display
-Typen table
zurückgreifen, was definitiv den Rahmen dieses Artikels sprengen würde.
Wer dennoch daran interessiert ist, kann sich gerne den
folgenden Pen dazu anschauen:
See the Pen Responsive Equal Height Columns without Flexbox by JR Cologne (@jr-cologne) on CodePen.
Falls Interesse am sogenannten Thema "Equal Height Columns" besteht, kann ich dies gerne in einem zukünftigen Artikel näher beleuchten.
Was ist mit Flexbox und dem Grid-Layout?
Genauso haben viele sicherlich auch Flexbox-Lösungen vermisst. Wie ihr schon merkt, handelt es sich bei diesem Artikel um einen sehr langen und ausführlichen. Um die Länge nicht noch weiter zu strapazieren, habe ich mich dazu entschieden, die Möglichkeiten mit Flexbox und dem neuen Grid-Layout nicht zu behandeln und stattdessen in einem zukünftigen Artikel ausführlich darauf einzugehen, wie man mit diesen vergleichsweise sehr neuen Technologien Elemente zentrieren kann.
Fazit
Zusammenfassend lässt sich sagen, dass das Zentrieren mit CSS, wie schon zuvor angedeutet, ein sehr umfangreiches Thema ist. Trotz allem hält sich der Schwierigkeitsgrad allerdings meist in Grenzen, vorausgesetzt man beschäftigt sich in Ruhe mit diesem Thema und macht sich bewusst, welche Faktoren zu beachten sind.
Des Weiteren hilft es enorm, wenn man sich zumindest grob mit den
unterschiedlichen display
-Typen und deren Eigenschaften
bzw. Verhalten auskennt, da dies einen der wichtigsten Faktoren
beim Zentrieren mit CSS darstellt.
Ansonsten kann ich zur allgemeinen Beruhigung noch sagen, dass man auch nicht jede einzelne Variante auswendig kennen muss, denn meist braucht man letztendlich dann doch nur zwei oder drei davon. Selbst in diesem doch sehr umfangreichen Artikel haben bei Weitem noch nicht alle Varianten Erwähnung gefunden.