Layouten mit Gridlayout und mit Flexbox im Vergleich
Geschrieben am:
Lange Zeit hatten wir keine vernünftige Layouttechnik – und jetzt haben wir gleich zwei: Flexbox und Gridlayout. Gridlayout ist mächtiger, das ist klar. Brauchen wir damit überhaupt noch Flexbox? Diese Frage beantwortet man am besten an praktischen Beispielen – hier zeige ich ein Sticky-Footer-Layout, das dann erweitert wird, und führe vor, wie man das Layout in seinen Variationen jeweils mit Gridlayout und mit Flexbox umsetzt.
Sticky-Footer
Beginnen wir mit einem einfachen Sticky-Footer, d.h. ein Layout mit Fußbereich, wobei sich der Fußbereich auch bei wenig Inhalt immer ganz unten befindet.
Die Basis ist folgender Code:
<body>
<header></header>
<article></article>
<footer></footer>
</body>
Sticky-Footer mit Flexbox
Sehen wir uns zuerst die Lösung mit Flexbox an:
body
erhält eine Höhe von 100vh
und wird zum Flexcontainer. Die Elemente sollten untereinander dargestellt werden – wofür flex-direction: column
sorgt.
body {
height: 100vh;
display: flex;
flex-direction:column;
}
((Ich nutze hier height
und nicht min-height
, damit der IE mitspielt, siehe Flexbox-Bugs.)) article
soll den gesamten übrigen Platz bekommen – das erreichen wir mit flex: 1
.
article { flex: 1; }
Sticky-Footer mit Flexbox ausprobieren
Sticky-Footer mit Gridlayout
Jetzt zur Lösung mit Gridlayout:
body
wird dieses Mal zum Gridcontainer und wir definieren das einfache Raster: Es soll drei Zeilen (grid-template-rows
) geben, die mittlere soll allen verfügbaren Platz einnehmen (1fr
):
body {
height: 100vh;
display: grid;
grid-template-rows: auto 1fr auto;
}
Sticky footer mit Gridlayout ausprobieren
Beide Lösungen funktionieren. Ein entscheidender Unterschied zeigt sich in der Herangehensweise: Bei Gridlayout definieren wir alles beim Gridcontainer – hier steht die wesentliche Logik. Bei Flexbox sind Informationen über die Platzverteilung hingegen beim Flexitem untergebracht - in unserem Fall bei article
, das allen verfügbaren Platz bekommen soll.
Welche Lösung ist besser?
Sehen wir uns einmal an, welche Lösung flexibler ist.
Erweitertes Layout – mit Flexbox
Erster Fall: Wir wollen eine weitere Zeile – beispielsweise für eine horizontale Navigation einführen.
Unser HTML-Code sieht damit folgendermaßen aus:
<body>
<header><h2>Header</h2></header>
<nav><h2>Nav</h2></nav>
<article><h2>Mittelteil</h2></article>
<footer><h2>Footer</h2></footer>
</body>
Weiterhin soll article
allen verfügbaren Platz einnehmen.
Bei der Flexbox-Lösung ist keinerlei Anpassung am CSS-Code notwendig.
Erweiterterer Sticky-Footer mit Flexbox
Erweitertes Layout mit Gridlayout
Bei Gridlayout müssen wir hingegen die Rasterdefinition anpassen – es sind jetzt schließlich vier Zeilen. Die Definition lautet jetzt grid-template-rows: auto auto 1fr auto;
body {
display: grid;
grid-template-rows: auto auto 1fr auto;
}
Erweitertes Sticky-Footer-Layout mit Gridlayout
Dass die Logik im Gridcontainer steckt, hat eben diesen Nachteil. Allgemein ist Flexbox die bessere Wahl, wenn es eben nur um die Anordnung in einer Richtung geht – im Beispiel geht es ja nur um die Anordnung untereinander.
Komplexeres Layout
Jetzt erweitern wir unser Beispiel einmal anders - wir wollen im Hauptteil nicht nur ein article
-Element, sondern drei:
<body>
<header><h2>Header</h2></header>
<article class="art1"><h2>Mittelteil</h2></article>
<article class="art1"><h2>Mittelteil</h2></article>
<article class="art1"><h2>Mittelteil</h2></article>
<footer><h2>Footer</h2></footer>
</body>
Die grundlegende Darstellung bleibt: d.h. der Footer soll ganz unten sein.
Komplexeres Layout mit Gridlayout
Bei der Umsetzung hat Gridlayout die Nase vorn. Und am einfachsten wird es, wenn man hier mit benannten Bereichen arbeitet:
body {
display: grid;
grid-template-areas:
"head head head"
"art1 art2 art3"
"foot foot foot";
grid-template-rows: auto 1fr auto;
grid-template-columns: auto auto auto;
}
Die entscheidende Definition ist grid-template-areas
: Hier lege ich die Aufteilung fest. Innerhalb der Anführungszeichen stehen jeweils die Bezeichnungen für eine Zeile, die einzelnen Strings innerhalb der Anführungszeichen definieren die einzelnen Spalten. In unserem Beispiel haben wir drei Zeilen und drei Spalten.
Wenn ein Element sich über mehrere Spalten erstrecken soll, so wiederhole ich den Namen. Die Bezeichnungen sind dabei frei gewählt.
Danach definiere ich die Ausmaße meines Rasters mit grid-template-rows
(Zeilen) und grid-template-columns
(Spalten). Die Größenangabe auto
ist nützlich, wenn die Elemente einfach so groß werden sollen, wie es der Inhalt erforderlich macht. 1fr
definiert, dass aller übriger Platz genutzt werden soll.
Danach weise ich im zweiten Schritt meine Elemente den oben definierten Bereichen zu:
header {
grid-area: head;
}
footer {
grid-area: foot;
}
.eins {
grid-area: art1;
}
.zwei {
grid-area: art2;
}
.drei{
grid-area: art3;
}
Dreispaltiges Sticky-Footer-Layout mit Gridlayout umgesetzt
Dreispaltiges Sticky-Footer-Layout mit Flexbox - Variante 1: geänderter Quellcode
Wie könnte man diese Aufteilung mit Flexbox lösen? Es gibt m.E. zwei Möglichkeiten: zum einen können wir Flexbox verschachteln. Das heißt, wir packen ein main
-Element um die drei Artikel. Damit haben wir einen geänderten Quellcode, nämlich folgendermaßen:
<body>
<header><h2>Header</h2></header>
<main>
<article class="art1"><h2>Mittelteil</h2></article>
<article class="art1"><h2>Mittelteil</h2></article>
<article class="art1"><h2>Mittelteil</h2></article>
</main>
<footer><h2>Footer</h2></footer>
</body>
Und dann hat main
eine Doppelrolle: Zum einen ist es Flexitem und nimmt den gesamten verfügbaren Platz in der Vertikalen ein. Zum anderen ist es selbst Flexcontainer für die article
-Items, die nebeneinander dargestellt werden. Und da die article
-Items den Platz unter sich aufteilen sollen, erhalten sie auch flex: 1
.
body {
display: flex;
flex-direction: column;
}
main {
display: flex;
flex: 1;
}
article {
flex: 1;
}
Dreispaltiges Sticky-Footer mit Flexbox - Variante 1 ausprobieren
Die Lösung klappt gut - aber wie gesagt mussten wir den HTML-Code verändern.
Dreispaltiges Sticky-Footer-Layout mit Flexbox - Variante 2: flex-wrap
Die andere Möglichkeit besteht im Einsatz von flex-wrap
. Wir nehmen die spaltenweise Darstellung (der Standard), aber dank flex-wrap
können die Elemente in die nächste Zeile gehen, wenn kein Platz mehr ist. Damit sich header
und footer
über die gesamte Breite erstrecken, erhalten sie eine flex-basis
von 100%. Die drei article
-Elemente sollen nebeneinander dargestellt werden und benötigen so eine Basisbreite von 33.3%:
body {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
header, footer {
flex-basis: 100%;
}
article {
flex-basis: 33.333%;
}
Außerdem sollen header
und footer
nicht ein Drittel des verfügbaren vertikalen Platz einnehmen, sondern ganz oben bzw. ganz unten angeordnet werden - dafür könnte ich mit align-self
arbeiten, aber ich nehme hier margin
.
header {
margin-bottom: auto;
}
footer {
margin-top: auto;
}
Dreispaltiges Sticky-Footer mit Flexbox -Variante 2 ausprobieren Bei dieser Lösung gibt es allerdings eine Einschränkung - wenn man den article
-Elementen Rahmen gibt (oder eine Hintergrundfarbe zuweist) - sieht man deutlich, dass die mittleren Elemente nicht den gesamten verfügbaren Platz einnehmen, sondern mittig angeordnet sind und nur so groß werden, wie es der Inhalt erfordert.
Das ist nicht immer ein Problem, aber es kann ein Problem sein. Dafür gibt es m.E. auch keine Lösung mit Flexbox. Und der Grund ist eben, dass Flexbox eindimensionale Steuerungen erlaubt und hier brauchen wir jetzt eine Steuerung in beide Richtung horizontal und vertikal - und genau dafür ist Gridlayout die bessere Wahl.
Fazit
Flexbox eignet sich gut für eindimensionale Layouts und ist dabei sehr flexibel, weil wir auch zusätzliche Elemente im HTML-Code ergänzen können, ohne etwas am CSS-Code ändern zu müssen. Für komplexere Layouts, d.h. Aufteilungen in der Horizontalen und in der Vertikalen, ist Gridlayout besser.