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.