Grid Layout/Benannte Linien und Rasterbereiche
Bei jedem Raster stellt sich die Frage nach der optimalen Anzahl und der Identifizierung der einzelnen Rasterelemente. Im Schach werden die Spalten mit den Buchstaben a-h, die Reihen oder Zeilen mit 1-8 gekennzeichnet. Im Printbereich hat sich ein 12er-Raster (wie bei bootstrap) bewährt, da es durch 2,3,4,6 teilbar ist und so viele verschiedene Kombinationen erlaubt.
Im WebDesign geht es eben aber nicht um ein Design für eine bestimmte Größe mit einem bestimten Seitenverhältnis, sondern um ein Design für eine Vielzahl von Viewports.
Deshalb wäre es gut, Rasterbereiche und ihre Rasterlinien nicht aufgrund ihrer Position, sondern mit ihrer semantischen Bedeutung kennzeichnen zu können. So kann das Seitenlayout in einem schnell zu erfassenden ASCII-Schema im CSS festgelegt werden.
Während Responsive Raster ohne Media Queries vor allem den auto-placement-Algorithmus vorstellte, zeigt dieses Tutorial, wie man feste Layouts mit wenig Aufwand im CSS festlegen und formatieren kann.
Inhaltsverzeichnis
Benannte Linien
Im vorhergehenden Kapitel zeigten wir bereits, wie man Rasterlinien nutzen kann. Mit grid-column und grid-row können Grid-Items innerhalb des Rasters positioniert werden:
-
grid-column: 1 / 6;: Das Rasterelement erstreckt sich von der ersten bis zur 6. Rasterlinie. -
grid-column: 1 / -1;: Es sind auch negative Werte möglich. Das Rasterelement erstreckt sich von der ersten bis zur letzten Rasterlinie.
Schwierig wird es, wenn sich das Raster ändert, wenn z. B. eine neue Spalte eingefügt wird.
Grid Layout bietet zusätzlich eine Alternative, die ganz ohne Mathematik auskommt! Anstelle von numerischen Werten kannst du den Rasterlinien auch semantische Namen geben, die das Positionieren der einzelnen Elemente ganz ohne Berechnungen erlaubt.[1][2]
body {
display: grid;
gap: 0.5em;
grid-template-columns:
[left] 1fr
[content-start] 3fr
[content-end] 1fr
[right];
}
header {
grid-column: left/ right;
}
#content {
grid-column: content-start / content-end;
}
Als Namen sind einerseits von dir selbstgewählte Zeichenketten erlaubt, noch einfacher ist andererseits das Verwenden der impliziten Namen:
Die Rasterlinien am Anfang einer grid-area können mit …-start , am Ende mit …-end aufgerufen werden. Umgekehrt erzeugen benannte Rasterlinien im CSS implizit auch eine solche grid-area:
Linien benennen und Elemente platzieren
body {
display: grid;
gap: 0.5em;
grid-template-columns:
[left] 1fr
[nav-start] 1fr
[content-start] 3fr
[content-end] 1fr
[right];
grid-template-rows:
min-content
[nav-start] 1fr
[aside-start] min-content;
[footer-start] min-content;
}
header {
grid-column: left/ right;
}
#content {
grid-column: content-start / content-end;
grid-row: nav-start / footer-start;
}
Der body wird mit dem schon bekannten grid-template-columns in 4 Spalten eingeteilt.
Die Werte für die Breiten werden jetzt nicht durch Leerzeichen, sondern durch in eckigen Klammern befindliche Liniennamen getrennt. Zusätzlich werden vor [nav-start] und nach [content-end] Spalten erzeugt, die den Seiteninhalt zentrieren, sonst aber leer bleiben.
Auch für die Zeilen werden mit grid-template-rows Liniennamen vergeben. Hier fällt auf, dass die oberste und unterste Reihe durch das Schlüsselwort min-content so klein wie möglich dargestellt werden sollen.
Die Kindelemente erhalten nun ihre Positionierungen. Anstelle eines Ausrechnens der Breiten und Höhen werden als Beginn und Ende der Elemente aber benannte Linien verwendet.
Rasterlinien mit mehreren Namen
Der Name content-end als Beginn des footers mag verwirrend sein. Deshalb können Rasterlinien mehrere Namen erhalten:
body {
display: grid;
gap: 0.5em;
grid-template-columns:
[left] 1fr
[nav-start] 1fr
[nav-end content-start] 3fr
[content-end margin-start] 1fr
[margin-end right];
grid-template-rows:
min-content
[nav-start main-top] 1fr
[aside-start] 1fr
[footer-start main-bottom] min-content;
}
#content {
grid-column: content-start / content-end;
grid-row: main-top / main-bottom;
}
Innerhalb der eckigen Klammern können mehrere, durch Leerzeichen getrennte, Liniennamen notiert werden.
So können die einzelnen Grid-Items noch genauer angesprochen werden.
Mehrere Rasterlinien mit dem gleichen Namen
Dieses Szenario tritt ein, wenn man die repeat()-Funktion im Zeilen- oder Spalten-Template verwendet und darin einen Liniennamen setzt. Um festzulegen, die wievielte Linie dieses Namens du meinst, gib die Liniennummer hinter dem Namen an:
body {
display: grid;
grid-template-columns:
[nav-start] 10em
repeat(3, [content] 1fr)
grid-template-rows: auto;
}
section:nth-of-type(1) {
grid-column: content 1 / span 1;
}
section:nth-of-type(2) {
grid-column: content 2 / span 1;
}
section:nth-of-type(3) {
grid-column: content 3 / span 1;
}
Benannte Rasterbereiche
In vielen Tutorials wird ein Vorteil von Grid Layout herausgestellt: Die Positionierung kann auch allein im Elternelement des Grid Containers vorgenommen werden:
body{
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-areas:
"head head head head"
"nav main main news"
"nav main main aside"
"foot foot foot foot";
}
Hier wird ein CSS-Grid-Layout mit benannten Bereichen definiert, das eine komplette Webseitenstruktur beschreibt.
grid-template-columns: repeat(4, 1fr); unterteilt das Raster in 4 gleich breite Spalten.
grid-template-areas beschreibt das Layout als Schema wie in einem wireframe oder einer ASCII-Zeichung.
- der
headerstreckt sich über alle vier Spalten -
navnimmt die linke Spalte über zwei Zeilen ein -
mainist der große zentrale Bereich (2 Spalten breit, 2 Zeilen hoch) -
newsundasidesitzen rechts oben und rechts unten
Wir bauen kein „klassisches Raster“ mehr, sondern zeichnen das Webseiten-Layout direkt im CSS.
Das bedeutet:
- Struktur wird sichtbar im Code
- Positionierung erfolgt über Namen statt Zahlen
- das Layout ist sofort als „Bild“ lesbar
Jeder Name in grid-template-areas steht für ein Grid-Item, das später mit der grid-area-Eigenschaft so zugewiesen wird:
header { grid-area: head; }
nav { grid-area: nav; }
main { grid-area: main; }
aside { grid-area: aside; }
#news { grid-area: news; }
Allerdings müssen die beiden aside-Boxen jetzt gesondert aufgeführt werden, da sie sich sonst überschreiben würden.
Auch im Seiteninspektor (hier Firefox 151) können die Rasterbereiche angezeigt werden:
Anpassungen an andere Viewports
Mit dieser Methode können Anpassungen an andere Viewports sehr schnell vorgenommen werden:
body {
display: grid;
gap: 0.5em;
grid-template-areas:
"head"
"main"
"nav"
"news"
"aside"
"foot";
}
@media (min-width: 35em) {
body {
grid-template-columns: repeat(3, 1fr);
grid-template-areas:
"head head head "
"nav news aside"
"main main main"
"foot foot foot";
}
}
@media (min-width: 45em) {
body {
grid-template-columns: repeat(4, 1fr);
grid-template-areas:
"head head head head"
"nav main main news"
"nav main main aside"
"foot foot foot foot";
}
}
Im Mobile First! werde alle Elemente untereinander dargestellt – allerdings wird die Navigation nach unten geschoben, damit der Hauptinhalt sicher im Viewport ist.
Bei einer Viewportgröße von mindestens 35em greift die media query, erzeugt 3 gleichbreite Spalten und schaltet die entsprechenden Werte für grid-template-areas um, sodass die Navigation und die Aside-Boxen nebeneinander dargestellt werden.
Ab 45em Breite werden vier Spalten und das „normale“ Desktop-Layout erzeugt.
Leerstellen
body {
display: grid;
gap: 0.5em;
grid-template-columns: 1fr 2fr 1fr;
grid-template-areas:
"head head head"
". main nav"
". main news"
"foot foot foot";
grid-template-rows:
min-content
[nav-start main-top] 1fr
[aside-start] 1fr
[footer-start main-bottom] min-content;
}
Der Header (head) und der Footer (foot) erstrecken sich jeweils über die gesamte Breite des Rasters.
Der Hauptinhalt (main) belegt in der Mitte einen Bereich über zwei Zeilen. Rechts daneben befinden sich die Bereiche nav und news.
Die Punkte (.) links kennzeichnen leere Rasterzellen, denen kein Rasterbereich zugeordnet ist. Sie bilden Weißraum, der den Focus auf den Inhalt in der Mitte legt.
Anwendungsbeispiele
Im CSS-Einstieg gibt es ein Beispiel, in dem als Dekoration ein Querbalken (engl. rule) eingefügt werden soll:
:root {
--navWidth: 12em;
--mainWidth: min(48em, calc(100% - var(--navWidth)));
--headerLineHeight: 3em;
}
@media (width > 30em) {
body {
display: grid;
grid-template: ". nav head ." auto
". nav rule ." var(--headerLineHeight)
". nav main ." auto
". nav foot ." auto /
1fr var(--navWidth) var(--mainWidth) 1fr;
}
body::before {
content: '';
grid-row: rule;
grid-column: 1 / 1;
background: linear-gradient(to right, var(--lila2), var(--lila1));
}
body::after {
content: '';
grid-row: rule;
grid-column: rule-start / -1;
background-image: linear-gradient(to right, var(--lila), var(--lila-darker));
}
}
Dieser Querbalken soll aber erst auf größeren Viewports sichtbar werden.
Im :root-Selektor werden die entsprechenden Werte schon in custom properties notiert. Ab einer Breite von 30em erhält der body zwei Pseudoelemente, die im Grid entsprechend platziert werden.
Formular
Formulare müssen klar und übersichtlich sein. Häufig wurde die Gestaltung durch zahlreiche wrapper-Elemente und Zeilenumbrüche erreicht. Mit dem Grid Layout können wir nun alle Formular-Elemente an einem Raster ausrichten:
form {
display: grid;
grid-template-columns: [labels] auto [controls] auto [oversized] auto;
grid-auto-flow: row dense;
}
form > label {
grid-column: labels;
grid-row: auto;
}
form > input, form > select {
grid-column: controls;
grid-row: auto;
}
#department-block {
grid-row: span 3;
grid-column: oversized;
}
#buttons {
grid-row: auto;
grid-column: 1 / -1;
text-align: end;
}
Das Formular form wird zu einem Raster mit drei Spalten, deren Größe inhaltsbasiert ist. Die entsprechende Rasterlinien erhalten aussagekräftige Namen.
Alle label-Elemente werden in die label-Spalte platziert; mit grid-row: auto; werden sie automatisch auf die Zeilen verteilt.
Analog wird mit den Eingabeelementen verfahren, die in der controls-Spalte platziert werden.
Das select-Menü mit der id department-block wird in die oversized-Spalte positioniert und umspannt dort 3 Zeilen (Auf mobilen Geräten wird das select-Menü durch ein Popup mit radio-Buttons ersetzt.)
Die Buttons werden von einem div umschlossen, das sich wegen grid-column: 1 / -1; über die gesamte Breite des Rasters erstreckt.
Periodensystem der Elemente
Die chemischen Elemente sind in einer Liste, die im Periodensystem nach steigender Kernladungszahl angeordnet sind. Dabei gibt es je nach Anzahl der Elektronen auf der Schale bestimmte Abstände.
Dies hat Gunnar Bittersmann in einem Pen mit grid-row und grid-column positioniert. Die Zahlen innerhalb der nth-of-type-Selektoren entsprechen der jeweiligen Ordnungszahl des Elements.
#periodic-table li:nth-of-type(2)
{
grid-column: 18;
}
#periodic-table li:nth-of-type(5),
#periodic-table li:nth-of-type(13)
{
grid-column: 13;
}
#periodic-table li:nth-of-type(n+58):nth-of-type(-n+71)
{
grid-row: lanthanides;
}
#periodic-table li:nth-of-type(n+90):nth-of-type(-n+103)
{
grid-row: actinides;
}
- codepen.io: Periodic table von Gunnar Bittersmann
Fazit
Mit den benannten Linien und mehr noch, mit den ASCII-Rastern kann man das Layout einer Webseite mit wenigen Zeilen CSS festlegen und über Media Queries entsprechend aktivieren. Allerdings müssen bei komplexeren Layouts oder anders aufgebauten Unterseiten neue Raster angelegt werden.
Weblinks
- ↑ MDN: Layout using named grid lines
- ↑ CSS-tricks: Using Grid Named Areas to Visualize (and Reference) Your Layout von Preethi Selvam on Aug 26, 2022
