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.