CSS Grid

Ein responsives Grid System für unterschiedliche Endgeräte und Plattformen mit CSS stellt Frontend-Entwicker immer wieder vor Herausforderungen.
Der Ansatz mit floating Elementen (float-basierten Rastern), den beispielsweise Bootstrap bis einschließlich Version 3 verfolgt hat, war wohl bis vor Kurzem die beste Variante, ein Grid System mit CSS zu implementieren.
Eine modernerer Variante, die dann auch Bootstrap ab Version 4 implementiert hat, ist Flexbox. Schwächen von Flexbox treten allerdings zutagen, wenn man komplexe Layouts mit ineinander verschachtelten Grid-Systemen umsetzen muss.
Neu ist jetzt CSS Grid, welches aktuell (Stand Oktober 2019) leider noch nicht von allen Browsern unterstützt wird.

Eine kurze Exkursion in die Flexbox Welt

Im Mittelpunkt eines Flexbox Layouts steht der sogenannte Flex-Container, in dem die Flex-Items angeordnet sind. Flex-Items werden innerhalb des Containers an einer so genannten Flex-Line ausgerichtet, die standardmäßig horizontal und linksbündig ausgerichtet ist.

Um nun Flexbox zu verwenden, wird dem Elternelement die CSS-Eigenschaft display mit dem Wert flex zugewiesen.
Alle Kindelemente des Containers werden nun als Flex-Items behandelt.

Beispiel 1: Flexbox Layout


<style scoped>
	.container {
		display:flex;
		width:100%;
		border:6px solid darkblue;
		box-sizing:border-box;
	}
	.container > div {
		width:20%;
		height:100px;
	}
	.container > div:nth-child(1) {
		background-color:yellow;
	}
	.container > div:nth-child(2) {
		background-color:orange;
	}
	.container > div:nth-child(3) {
		background-color:lightgreen;
	}
	.container > div:nth-child(4) {
		background-color:lightblue;
	}
</style>
<div class="container">
	<div>Flex-Item 01</div>
	<div>Flex-Item 02</div>
	<div>Flex-Item 03</div>
	<div>Flex-Item 04</div>
</div>

Will man nun die Flex-Items rechtsbündig anordnen, erreicht man dies indem man für das Container-Element die CSS-Eigenschaft flex-direction auf den Wert row-reverse setzt.

Beispiel 2: Rechtsbündige Flex-Items

Die Reihenfolge der einzelnen Flex-Items kann man unabhängig ihrer Position über die CSS-Eigenschaft order bestimmen.
Die Größe der Kindelemente lässt sich mit der Eigenschaft flex beeinflussen. Hierbei orientieren sich die Flex-Items immer in Relation zum Elternelement.

Beispiel 3: Größe der Flex-Items mit der CSS-Eigenschaft flex


<style scoped>
	.container {
		display:flex;
		width:100%;
		border:5px solid darkblue;
		box-sizing:border-box;
	}
	.container > div {
		width:100px;
		height:100px;
	}
	.container > div:nth-child(1) {
		background-color:yellow;
		flex:3;
	}
	.container > div:nth-child(2) {
		background-color:orange;
		flex:1
	}
	.container > div:nth-child(3) {
		background-color:lightgreen;
		flex:1;
	}
	.container > div:nth-child(4) {
		background-color:lightblue;
		flex:2;
	}
</style>
<div class="container">
	<div>Flex-Item 01</div>
	<div>Flex-Item 02</div>
	<div>Flex-Item 03</div>
	<div>Flex-Item 04</div>
</div>

Für die Umsetzung von responsiven Layouts ist es nun nötig, dass sich die Elemente innerhalb eines Containers bei sich ändernder Bildschirmbreite neu anordnen. Dies erreicht man, indem man für das Container-Element die CSS-Eigenschaft flex-wrap auf den Wert wrap setzt.

Beispiel 4: Größe der Flex-Items mit der CSS-Eigenschaft flex


<style scoped>
	.container {
		width:100%;
		border:5px solid darkblue;
		box-sizing:border-box;
		display:flex;
		flex-wrap: wrap;
	}
	.container > div {
		width:50%;
		height:100px;
	}
	.container > div:nth-child(1) {
		background-color:yellow;
	}
	.container > div:nth-child(2) {
		background-color:orange;
	}
	.container > div:nth-child(3) {
		background-color:lightgreen;
	}
	.container > div:nth-child(4) {
		background-color:lightblue;
	}
</style>
<div class="container">
	<div>Flex-Item 01</div>
	<div>Flex-Item 02</div>
	<div>Flex-Item 03</div>
	<div>Flex-Item 04</div>
</div>

Mithilfe von Media-Queries kann man das Layout nun an die Auflösung des Endgeräts anpassen, also responsiv gestalten.

Zusätzlich zu den genannten CSS-Eigenschaften für Flexbox gibt es noch die Eigenschaften flex-flow, justify-content, flex-basis, align-items, align-content, align-self, flex-shrink und flex-grow, auf die ich hier nicht näher eingehen werde.

CSS Grid

Mit Flexbox besteht eine Technik, mit der man eindimensionale Layouts umsetzen kann. CSS Grid ermöglicht einem jedoch das Umsetzen komplexer zweidimensionaler Layouts.

In einem CSS Grid Layout wird ein Elternelement definiert, an dem dann das Raster festgelegt wird. Die darin enthaltenen Kindelemente werden dann am Raster positioniert.
Das Elternelement bekommt hier die CSS-Eigenschaft display mit dem Wert grid. Das Raster wird über die Eigenschaften grid-template-columns und grid-template-rows aufgebaut.

Die Kindelemente innerhalb des Elternelements ordnen sich automatisch zeilenweise von oben links nach unten rechts an.
Mit der CSS-Eigenschaft grid-auto-flow kann man beeinflussen, wie sich die Kindelemente anordnen

Mit den CSS-Eigenschaften grid-column-start, grid-column-end, grid-row-start und grid-row-end können die Kindelemente auch komplett frei im Raster positioniert werden.
Hier kann auch die Kurzschreibweisen grid-column bzw. grid-row mit jeweils dem Start- und End-Wert genutzt werden.

Beispiel 5: CSS Grid Layout mit im Raster positionierten Kindelementen

>
<style scoped>
	.container {
		width:100%;
		border:5px solid black;
		box-sizing:border-box;
		display:grid;
		grid-template-columns: 100px 1fr 100px;
		grid-template-rows: 80px 1fr 80px;
	}
	.header-container {
		grid-column: 1 / 4;
		grid-row: 1 / 2;
		background-color:lightblue;
	}
	.left-container {
		grid-column: 1 / 2;
		grid-row: 2 / 3;
		background-color:lightgreen;
	}
	.main-container {
		grid-column: 2 / 3;
		grid-row: 2 / 3;
		background-color:orange;
	}
	.right-container {
		grid-column: 3 / 4;
		grid-row: 2 / 3;
		background-color:yellow;
	}
	.footer-container {
		grid-column: 1 / 4;
		grid-row: 3 / 4;
		background-color: lightgrey;
	}
</style>
<div class="container">
	<div class="header-container">CSS-Grid</div>
	<div class="main-container">
		<h1>This is the main content container</h1>
		<p>This is the main content container</p>
		<p>This is the main content container</p>
		<p>This is the main content container</p>
	</div>
	<div class="left-container">Left Sidebar</div>
	<div class="right-container">Right Sidebar</div>
	<div class="footer-container">Footer</div>
</div>

Achtung! Die Positionierung der Kindelemente erfolgt nicht über Spalten im Raster, sondern über Linien. grid-row: 3 / 4 bedeutet also beispielsweise, dass das Element von der dritten Linie (Anfang der dritten Spalte) bis zur vierten Linie (Ende der dritten Spalte) reicht.

1fr ist hier übrigens eine neue Einheit. Sie bedeutet quasi "ein Teil des zur Verfügung stehenden Platzes".

 

Die Kindelemente können dem Raster ebenfalls auch über eine Benennung zugewiesen werden. Dies geschieht über die Eigenschaft grid-area am Kindelement und die Eigenschaft grid-template-areas am Elternelement.

Beispiel 6: CSS Grid Layout mit benannten Raster-Bereichen

<style scoped>
	.container {
		width:100%;
		border:5px solid black;
		box-sizing:border-box;
		display:grid;
		grid-template-areas: "header header header"
					"left main right"
					"footer footer footer";
		grid-template-columns: 100px 1fr 100px;
		grid-template-rows: 80px 1fr 80px;
	}
	.header-container {
		grid-area: header;
		background-color:lightblue;
	}
	.main-container {
		grid-area: main;
		background-color:orange;
	}
	.left-container {
		grid-area: left;
		background-color:lightgreen;
	}
	.right-container {
		grid-area: right;
		background-color:yellow;
	}
	.footer-container {
		grid-area: footer;
		background-color: lightgrey;
	}
</style>
<div class="container">
	<div class="header-container">CSS-Grid</div>
	<div class="main-container">
		<h1>This is the main content container</h1>
		<p>This is the main content container</p>
		<p>This is the main content container</p>
		<p>This is the main content container</p>
	</div>
	<div class="left-container">Left Sidebar</div>
	<div class="right-container">Right Sidebar</div>
	<div class="footer-container">Footer</div>
</div>

Die Anpassung an die unterschiedlichen Endgeräte geschieht nun wieder über Media-Queries.

 

Weitere CSS-Eigenschaften sind grid-row-gap und grid-column-gap mit denen sich am Elternelement die Abstände zwischen den Kindelementen definieren lassen. Hier gibt es auch wieder die Kurzschreibweise grid-gap.

Ebenfalls am Elternelement kann man über die CSS-Eigenschaften justify-items die horizontale Ausrichtung und align-items die vertikale Ausrichtung bestimmen.
Einzelne Kindelemente lassen sich über die Eigenschaft justify-self und align-self ausrichten.

Den Browser Support für CSS Grid können Sie folgender Seite entnehmen: https://caniuse.com/#feat=css-grid
Einen Polyfill für CSS Grid finden Sie hier: https://github.com/FremyCompany/css-grid-polyfill.