- CSS Grid wird seit März 2017 von den großen Browsern breit unterstützt, doch
grid-template-areas wird weiterhin seltener genutzt und kann Layouts ohne Berechnung von Zeilennummern visuell in CSS darstellen
grid-template-areas platziert Bereichsnamen als Strings und verbindet sie über grid-area mit Kindelementen; gleiche Namen müssen stets einen rechteckigen Bereich bilden
- Benannte Grid-Linien versehen Linien mit Namen wie
content-start / content-end; Muster wie *-start und *-end können vom Browser wie implizite Bereiche genutzt werden
- Bei umgedrehten Karten, responsiven Headern, Editorial-Layouts, Posts im Threads-Stil, überlappenden Karten und bedingten Layouts mit
:has() lassen sich Layout-Varianten verwalten, indem nur der Bereichs-String des Elternteils geändert wird
- Chrome, Safari und Firefox bieten alle DevTools für Grid-Bereiche; besonders nützlich ist Firefox mit der Anzeige von Bereichsnamen und Autovervollständigung für mögliche Liniennamen beim Bearbeiten von
grid-area
Layouts mit grid-template-areas lesbarer machen
- Bei herkömmlichen CSS-Grid-Layouts ist es üblich, Zeilennummern direkt anzugeben, etwa
grid-column: 1 / 3
- Zeilennummern sind erst in den DevTools sichtbar, und bei Layouts mit Spalten und Zeilen ist es schwierig, die richtigen Nummern im Kopf zu berechnen
grid-template-areas versieht jede Zelle mit einem Namen, sodass der CSS-Code selbst wie eine Karte des Layouts aussieht
.page {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-areas: "item1 item2";
gap: 1rem;
}
.item-1 {
grid-area: item1;
}
.item-2 {
grid-area: item2;
}
- Kindelemente werden über
grid-area auf benannte Bereiche gemappt
- Im Kartenbeispiel kann man etwa
"featured featured article" definieren, sodass der Bereich featured zwei Spalten und der Bereich article eine Spalte belegt
Syntax und zwingende Regeln
grid-template-areas nimmt einen oder mehrere Bereichs-Strings entgegen
- Ein einzelner String erzeugt ein eindimensionales Layout nur mit Spalten
- Mehrere Strings bilden ein mehrdimensionales Layout mit Zeilen und Spalten
- Bei mehreren Strings macht ein Zeilenumbruch das Layout leichter lesbar
.element {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-areas:
"aside main"
"footer footer";
}
- Jeder String steht für eine Zeile des Grids; man kann es sich wie eine Tabelle vorstellen
- Bereiche mit demselben Namen müssen im Code rechteckig sein
/* invalid */
.layout {
grid-template-areas:
"header header"
"sidebar main"
"header footer";
}
/* valid */
.layout {
grid-template-areas:
"header header"
"sidebar main"
"sidebar footer";
}
- Alle Zeilen müssen dieselbe Anzahl an Bereichs-Tokens haben; auch wenn ein benötigter Bereich nicht verwendet wird, muss die Zelle selbst definiert werden
- Leere Zellen können mit einem einzelnen Punkt oder mehreren Punkten dargestellt werden
.element {
grid-template-areas:
"aside main"
"... footer";
}
- Der Punkt ist in der CSS-Grid-Spezifikation ein Null-Cell-Token und steht für eine leere Grid-Zelle
Verhältnis zwischen benannten Grid-Linien und Bereichen
- In CSS Grid gibt es eine Linie mehr als Spalten
- Bei 3 Spalten entstehen also 4 Grid-Linien
- Benannte Grid-Linien versehen Linien statt der Standardnummern mit eindeutigen Namen
.layout {
grid-template-columns:
[full-start] 1fr
[content-start] 2fr
[content-end] 1fr [full-end];
}
.item {
grid-column: content-start / content-end;
}
- Auch wenn Linien Namen haben, können numerische Linien weiterhin verwendet werden
- Die Track-Größe (track size) bezeichnet die Größe einer Spalte oder Zeile; Werte wie
1fr 1fr sind Track-Größen
- Bei benannten Linien werden die Linien rund um einen Track benannt
.layout {
display: grid;
grid-template-columns:
[aside-start] 200px [aside-end main-start] 1fr [main-end];
}
- Eine Linie kann mehrere Namen teilen; im obigen Beispiel sind
aside-end und main-start dieselbe Linie
- Definiert man Namen wie
aside-start und aside-end nach dem Muster *-start / *-end, erlaubt der Browser über implizite Liniennamen Verwendungen wie grid-column: aside
- Es ist nicht nötig, alle Linien zu benennen; wichtige Linien können gezielt benannt werden
- Bei der Platzierung lassen sich Zahlen und Namen mischen, etwa
grid-column: 1 / content-end
Layout-Varianten über Bereichs-Strings des Elternteils verwalten
- Mit
grid-template-areas kann man den Namen grid-area der Kindelemente beibehalten und das gesamte Layout ändern, indem nur die Bereichs-Strings des Elternteils angepasst werden
.aside {
grid-area: aside;
}
.main {
grid-area: main;
}
.footer {
grid-area: footer;
}
- Behält man dieselben Namen
aside, main und footer bei und ändert nur die Strings in grid-template-areas, wird die gesamte Anordnung automatisch aktualisiert
- Die Layout-Steuerung wird in der Bereichsdefinition des Elternteils zentralisiert, was Anpassungen erleichtert
Kartenrichtung umkehren
- In Flexbox lässt sich die Kartenrichtung mit
flex-direction: row-reverse leicht umkehren
- Nutzt man in CSS Grid Zeilennummern, muss man beim Ändern der Richtung die Spaltendefinitionen und die
grid-column-Werte jedes Kindelements gemeinsam anpassen
- Mit benannten Bereichen weist man Bild und Inhalt der Karte Bereichen zu und ändert anschließend nur die Reihenfolge der Bereiche im Elternteil
.card {
display: grid;
grid-template-columns: 150px 1fr;
grid-template-areas: "thumb content";
}
.card__thumb {
grid-area: thumb;
}
.card__content {
grid-area: content;
}
.card--flip {
grid-template-columns: 1fr 150px;
grid-template-areas: "content thumb";
}
- Dasselbe Layout lässt sich auch mit der Kurzschreibweise
grid-template ausdrücken
.card--flip {
grid-template: "content image" / 1fr 150px;
}
- Die Kurzschreibweise ist optional; man kann sich auch dafür entscheiden, die langen Eigenschaften als besser lesbar zu betrachten
Responsives Header-Layout
- Ein Header mit Logo, Navigation und Aktionsbereich kann zunächst aus drei gleich großen Spalten bestehen
- Mit Zeilennummern müsste man für
.logo, .nav und .actions jeweils grid-column angeben
- Mit Bereichsnamen mappt man die Kindelemente auf
logo, nav und actions und ändert je nach Viewport nur grid-template-areas des Elternteils
.header {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-areas: "logo nav actions";
}
.logo {
grid-area: logo;
}
.nav {
grid-area: nav;
}
.actions {
grid-area: actions;
}
- Bei kleineren Größen kann man Logo und Aktionen in die erste Zeile setzen und die Navigation über die volle Breite laufen lassen
.header {
grid-template-areas:
"logo logo actions"
"nav nav nav";
}
- Ab
380px kann das Logo links stehen, während Navigation und Aktionen rechts platziert werden
@media (min-width: 380px) {
.header {
grid-template-areas:
"logo nav nav"
"logo actions actions";
}
.nav {
justify-self: end;
}
}
- Ab
900px kann man zur einzeiligen Anordnung zurückkehren
@media (min-width: 900px) {
.header {
grid-template-areas: "logo nav actions";
}
}
- Bereichs-Strings funktionieren wie ein Mapping, das die UI-Anordnung direkt im CSS zeigt
Beispiel für ein Editorial-Layout
- Ein Abschnitt mit Titel, Text und Bild kann mit
grid-template-areas je nach Viewport-Größe leicht anders angeordnet werden
.section {
display: grid;
grid-template-areas:
". title title"
"thumb content content";
gap: 1rem;
}
- Der Punkt links vom Titel ist ein Null-Cell-Token, das einen leeren Raum markiert
- Im Beispiel eines Abschnitts im Stil von time.com werden die Bereiche
feature, secondary und most-read zusammen mit leeren Spalten auf beiden Seiten verwendet
.featured-section {
display: grid;
grid-template-areas:
". feature most-read ."
". secondary most-read .";
grid-template-columns: 1fr minmax(auto, 57.313rem) minmax(12rem, 18.75rem) 1fr;
grid-template-rows: minmax(auto, 25rem) 1fr;
}
- Die leeren Spalten an beiden Seiten dienen vor allem als horizontaler Abstand
- In der responsiven Version werden
feature, secondary und most-read auf kleinen Bildschirmen vertikal gestapelt; ab 500px und 900px werden Spalten- und Bereichsdefinitionen geändert
grid-template-rows kann durch Bereichsdefinitionen ersetzt werden und ist daher nicht zwingend erforderlich
Post-Komponente im Threads-Stil
- Beim Durchsehen des CSS der Threads-App von Meta lassen sich Einsatzbeispiele für CSS Grid in einer Post-Komponente finden
- Das ursprüngliche Beispiel platziert Items mit
grid-template-columns, grid-template-rows und Zeilennummern
.postBody {
grid-column-start: 2;
grid-row-start: 2;
grid-row-end: span 3;
}
- Mehrere Post-Varianten lassen sich mit
grid-template-areas leichter ausdrücken
.post {
grid-template-areas:
"avatar header"
"avatar body"
". body"
". footer";
}
.post--reply {
grid-template-rows: 40px max-content max-content;
grid-template-areas:
"avatar header"
"body body"
"body body"
"footer footer";
}
.post--nested {
grid-template-areas:
"avatar header"
"avatar body"
"line body"
"footer footer";
}
- Basis-, Antwort- und verschachtelte Post-Varianten lassen sich allein anhand der Bereichs-Strings unterscheiden
Überlappende Items und Bereichsnamen
- Da gleiche Namen in
grid-template-areas rechteckig sein müssen, ist es ungültig, denselben Namen in einer nicht rechteckigen Form zu wiederholen
.layout {
display: grid;
grid-template-columns: 1fr 1fr fr;
grid-template-areas:
"card tag tag"
"title title card";
}
- Das obige Beispiel ist invalid, weil
card kein Rechteck bildet
- Bei überlappenden Karten kann man neue Bereichsnamen wie
thumb-1 und thumb-2 definieren und diese Namen in grid-column und grid-row verwenden
.card {
display: grid;
grid-template-columns: auto auto 1fr;
grid-template-rows: auto auto;
grid-template-areas:
"thumb-1 tag"
"title thumb-2";
}
.thumb {
grid-column: thumb-1 / thumb-2;
grid-row: thumb-1 / thumb-2;
}
- Tag und Titel können jeweils in
grid-area platziert und mit align-self sowie justify-self ausgerichtet werden
- Falls nötig, muss die Stapelfolge der Kindelemente verwaltet werden; im Beispiel reicht jedoch die Source-Reihenfolge aus
- Dieses Überlappungsbeispiel ist von der Seite Oddbird’s Cascading Layouts inspiriert
:has() und bedingte Layouts
- Kombiniert man den CSS-Selektor
:has() mit Grid-Bereichen, lässt sich das Layout abhängig davon ändern, ob ein bestimmtes Element vorhanden ist
- Für ein
<figure> mit und ohne figcaption können unterschiedliche Bereichsdefinitionen angewendet werden
figure {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-areas: "img img img";
gap: 0.5rem;
}
img {
grid-area: img;
}
figcaption {
grid-area: caption;
}
.card:has(figcaption) {
grid-template-areas:
"img img caption"
"img img .";
}
Unterstützung für mehrsprachige LTR/RTL-Richtungen
- CSS Grid passt das Layout daran an, ob die Seitenrichtung LTR oder RTL ist
- Auch benannte Grid-Bereiche folgen der Seitenrichtung, sodass sich das Layout bei einer RTL-Einstellung umkehrt
- Als Material zum Erstellen von RTL-Layouts gibt es den Leitfaden RTL Styling 101
Unterschiede bei der DevTools-Unterstützung
- Chrome, Safari und Firefox bieten alle DevTools für Grid-Bereiche
- Chrome
- Platziert Bereichsnamen oben links, wodurch Bereiche überlappt wirken können
- Farb-Overlays können verändern, wie das Design wahrgenommen wird
- Safari
- Eine pinke Kontur hilft dabei, Items klar voneinander zu unterscheiden
- Liniennamen sind sichtbar
- Die Darstellung der Liniennamen könnte verbessert werden, etwa durch eine gestapelte Anzeige der Zeilen
- Firefox
- Bereichsnamen sind klarer sichtbar als in Chrome und Safari
- Bietet eine Autovervollständigungsliste beim Eingeben benutzerdefinierter Namen wie
*-start und *-end
- Bietet beim Bearbeiten von
grid-area eines Kindelements eine Liste aller möglichen Liniennamen
Referenzen
1 Kommentare
Meinungen auf Hacker News
Die Animationsdemo war ziemlich interessant, aber es war enttäuschend, als sich herausstellte, dass diese Animation nicht mit CSS gemacht war.
Nachdem ich Flexbox gelernt hatte, dachte ich: „Das reicht völlig“, und habe Grid nicht vertieft gelernt. Es scheint Gründe zu geben, Grid zu bevorzugen [0], aber insgesamt hatte ich nie etwas zu tun, das nur mit Grid möglich gewesen wäre; für Datentabellen verwende ich tatsächlich
<table>.[0] https://css-tricks.com/css-grid-replace-flexbox/
Grid habe ich nur für responsive Bildergalerien wie https://labs.jensimmons.com/2016/examples/image-gallery-grid... oder responsive Cards wie https://every-layout.dev/demos/grid-cards/ verwendet.
grid-template-columnsist es wert, gelernt zu werden, undgrid-gapist praktisch. Ansonsten habe ich das Gefühl, dass Flexbox fast alles erledigt.Allerdings bleibt
grid-template-areasfür mich noch etwas unklar. Der Artikel nennt als Argumente, dass Layout-Anpassungen je Breakpoint einfacher seien oder dass es leichter sei, „wenn ein Teammitglied das Layout ändern muss“, aber vielleicht bin ich einfach nicht die Zielgruppe.Man kann je nach Bedarf beides verwenden, und zusammen ergeben sie ein sehr mächtiges Layout-Werkzeug.
https://www.youtube.com/watch?v=MWWcZzossc8
Moment,
1/3ist kein Bruch, sondern ein Bereich von 1 bis 3? Ich verstehe nicht, warum man ausgerechnet diese Syntax gewählt hat. In der Programmierung gibt es viele vernünftige und gut bekannte Schreibweisen für Bereiche, zum Beispiel1..3.Viele Probleme, die Programmierer mit CSS haben, scheinen aus diesem Missverständnis zu entstehen.
!importantin CSS nicht „nicht wichtig“, sondern „wichtig!“ bedeutet.Weder Grid noch Flexbox habe ich richtig im Griff. Die letzte Layout-Strategie, mit der ich einigermaßen gut zurechtkam, war float. Dieser Artikel hat mir Selbstvertrauen gegeben, beim nächsten Layout-Entwurf CSS Grid auszuprobieren, und er ist auch gut gemacht.
Es gibt viele gute Artikel, aber für mich haben diese beiden Artikel von CSS-Tricks gereicht:
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
https://css-tricks.com/snippets/css/complete-guide-grid/
Zusätzlich zu den bereits genannten CSS-Tricks-Artikeln empfehle ich den Flexbox-Guide von MDN[1] und die Referenz zu „CSS flexible box layout“[2]. Sie haben mir geholfen, die Konzepte hinter Flexbox, die Eigenschaften und die Kurzschreibweisen sowie deren tatsächliches Verhalten besser zu verstehen.
[1]: https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layou...
[2]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_flexibl...
Allerdings ist auch Flexbox eher ein eindimensionales Layout mit möglichem Umbruch, daher besteht der Trick im Verschachteln und Stapeln. Grid hat Templates, und direkte Kindelemente belegen vorab definierte Bereiche; dadurch ist es statischer als Flexbox und hat die Einschränkung, dass es verschachtelte innere Elemente nicht beeinflusst. Trotzdem scheint subgrid diesen Teil verändern zu können.
Verwandte Ressourcen:
Grid Garden https://cssgridgarden.com
Flexbox Froggy https://flexboxfroggy.com
Ich fände es gut, wenn es eine noch grundlegendere Version „vor dem Einstieg“ gäbe. Ich bin schon im Einführungsteil hängengeblieben und kam nicht weiter. Besonders bei der Stelle „Um Kindelemente innerhalb des Grid zu platzieren, muss man mit
grid-columnfür jedes Element die Zeilennummern angeben“ wusste ich nicht, was hier mit Zeilennummern gemeint ist.Ich habe versucht, es aus dem Kontext zu erschließen und weiterzumachen, blieb dann aber sofort wieder bei Ausdrücken wie
1 / 3und1 / 4hängen.|a||b|zählen die beiden Linien in der Mitte tatsächlich als eine, also insgesamt 3.Daher ist
1/3kein Bruch, sondern ein Spaltenbereich und bedeutet: „beginnt an Linie 1 und endet an Linie 3“.Der Name „Zeilennummer“ ist nicht besonders gut, aber tatsächlich handelt es sich um die Kanten der Spalten.
1/3geht also von der 1. Kante, ganz links, bis zur 3. Kante und nimmt damit die gesamten 2 Spalten ein.Für CSS Grid empfehle ich Jen Simmons Mondrian with auto flow sehr. Auf https://labs.jensimmons.com/2017/01-011.html einfach
CundDdrücken und die Fenstergröße ändern. Es gibt auch ein begleitendes YouTube-Video: https://www.youtube.com/watch?v=qNtJ5p3h2A4Wirklich großartig.
Was ich bei auto flow noch verstehen möchte, ist, wie man Lücken erkennt und füllt. Wenn Objekte unterschiedlicher Größe zufällig verteilt sind: Wie sorgt man dafür, dass auto flow keine Lücken lässt? Oder kann man Lücken erkennen und etwas hinzufügen?
Ich hoffe, das ist keine dumme Frage, aber warum wurde die Syntax mit einem Slash wie
1/2,3/4definiert? Wäre etwas wie1-2, also von Spalte 1 bis Spalte 2, oder1->2nicht natürlicher?1--1,1->-1oder1/-1?In CSS werden Werte ohnehin schon durch Leerzeichen getrennt, und wenn man die übliche Intuition bei Bindestrichen berücksichtigt, ist Folgendes viel besser:
grid-column: 4 somegridarea / 6;grid-column: span 3 / 6;grid-column: span somegridarea / span someothergridarea;Es ist deutlich klarer als so etwas:
grid-column: 4 somegridarea-6;grid-column: span 3-6;grid-column: span 3->6;grid-column: span somegridarea-span someothergridarea;grid-column: span somegridarea->span someothergridarea;Solche interaktiven Blogartikel finde ich wirklich gut. Bei Grid kann ich sehr empfehlen, die Grid Areas in Tools wie https://grid.layoutit.com/ direkt auszuprobieren.
Ich plane seit Jahren Grid-Layouts mit dieser Website, und das Anpassen der Abstände ist dadurch viel einfacher geworden.
Vielleicht ist das das erste Mal, dass ich CSS Grid wirklich verstanden habe. Die Nummernanzeige war enorm hilfreich, und ich werde diesen Artikel künftig oft als Referenz nutzen.
Ich mag CSS Grid und das Konzept der Areas, aber der schwierigste Teil bleibt für mich weiterhin das responsive Management, insbesondere zwischen Mobil- und Desktop-Größen. Je nachdem, welche UI-Elemente geöffnet sein sollen oder ob etwas im Vollbild angezeigt werden soll, muss man
grid-template-areasowie Zeilen-/Spaltengrößen oft per JavaScript aktualisieren.Ich habe noch keine Welt gefunden, in der sich das mit
minmaxodercalclösen lässt, und ich hoffe, jemand kennt die Antwort.var(--foo)zu definieren.Dann muss JavaScript nur den Wert dieser Variable aktualisieren, und Grid übernimmt ihn.
display: none.Ein sehr einfaches Beispiel: https://codepen.io/trescenzi/pen/vYqpjvL
:has()oder subgrid lösen, aber ich habe damit selbst nicht viel Erfahrung.