Vor CSS Grid bedeutete der Aufbau eines ordentlichen Seitenlayouts Floats, Clearfixes, negative Margins und ein Gebet, dass die Spalten nicht zusammenbrechen. Flexbox half, aber es ist grundlegend eindimensional — man bekommt eine Zeile oder eine Spalte, nicht beides. CSS Grid ist das erste native CSS-Layoutsystem, das tatsächlich für zweidimensionale Layouts konzipiert wurde. Die Herausforderung liegt nicht bei der Browserunterstützung — diese ist seit 2017 universell. Die Herausforderung ist, dass die API viel Oberfläche hat und die Benennung inkonsistent genug ist, um verwirrend zu sein, wenn man das zugrunde liegende Modell nicht klar hat. Dieser Artikel konzentriert sich auf die Teile, die man in der echten Arbeit verwenden wird.

Zeilen, Spalten und der Grid-Container

Alles beginnt mit display: grid am Container. Sobald gesetzt, werden die direkten Kinder automatisch zu Grid-Elementen — keine Klasse ist auf ihnen nötig. Man definiert die Spalten- und Zeilenspuren mit grid-template-columns und grid-template-rows.

Die wichtigste Einheit, die man zunächst verstehen muss, ist fr — die fraktionelle Einheit. Sie stellt einen Bruchteil des verfügbaren Raums im Grid-Container dar, nachdem Spuren mit fester Größe berücksichtigt wurden. Ein 1fr bedeutet „nimm einen Anteil vom verbleibenden Platz." Zwei Spalten von 1fr 1fr bedeutet gleiche Hälften. 2fr 1fr bedeutet, dass die erste Spalte doppelt so viel erhält wie die zweite. Diese Einheit macht fluide Grids natürlich erscheinen.

css
/* 3-column blog card layout */
.card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: auto;
  gap: 1.5rem;
}

/* repeat(3, 1fr) is shorthand for: 1fr 1fr 1fr */
/* auto rows size to their content */

repeat(n, track) ist eine Kurzform, damit man nicht dieselbe Spurgröße fünfmal schreiben muss. Es funktioniert auch mit gemischten Werten: repeat(3, 1fr 2fr) ergibt ein 6-spaltiges Grid, das zwischen schmalen und breiten Spuren wechselt. Für Zeilen ist auto fast immer das, was man möchte — Zeilen richten sich nach ihrem Inhalt, es sei denn, man benötigt explizit eine feste Höhe.

html
<div class="card-grid">
  <article class="card">
    <img src="/posts/grid-post-1.jpg" alt="CSS Grid post 1">
    <h2>Getting Started with Grid</h2>
    <p>A practical intro for developers moving from Flexbox.</p>
  </article>
  <article class="card">
    <img src="/posts/grid-post-2.jpg" alt="CSS Grid post 2">
    <h2>Grid vs Flexbox</h2>
    <p>Which layout tool to reach for, and when.</p>
  </article>
  <article class="card">
    <img src="/posts/grid-post-3.jpg" alt="CSS Grid post 3">
    <h2>Responsive Grids Without Media Queries</h2>
    <p>Using minmax() to handle reflow automatically.</p>
  </article>
</div>

Die gap-Eigenschaft

Vor Grid bedeutete das Hinzufügen von Abständen zwischen Layout-Kindern Margins — und Margins bedeuteten, sich daran zu erinnern, das letzte Kind zurückzusetzen, Kollaps zu behandeln und negative Margins auf dem Container hinzuzufügen, um zu kompensieren. gap löst dies sauber. Es fügt Raum nur zwischen Spuren ein, niemals an den Außenkanten des Grids.

css
/* Uniform gap between all rows and columns */
.card-grid {
  gap: 1.5rem;
}

/* Different row and column gaps */
.dashboard {
  row-gap: 2rem;
  column-gap: 1rem;
}

/* gap is shorthand: row-gap then column-gap */
.dashboard {
  gap: 2rem 1rem;
}
Hinweis: gap funktioniert auch in Flexbox (es ersetzte den alten grid-gap-Alias). Wenn man Flexbox bereits für eine Komponente verwendet und nur Abstand zwischen Elementen benötigt, kann man gap dort ebenfalls verwenden, ohne zu Grid zu wechseln.

Elemente explizit platzieren

Standardmäßig fließen Grid-Elemente in die nächste verfügbare Zelle in der Quellreihenfolge. Aber die wahre Stärke von Grid liegt darin, dass man Elemente überall platzieren — und sie sogar mehrere Spuren überspannen lassen kann. Die Eigenschaften sind grid-column und grid-row, die auf Grid-Linien verweisen (die Linien zwischen Spuren, nummeriert ab 1).

css
/* Dashboard where the first card spans 2 columns */
.dashboard {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
}

.card--featured {
  grid-column: 1 / 3;   /* start at line 1, end at line 3 */
}

/* span keyword: simpler when you don't care about exact position */
.card--featured {
  grid-column: span 2;  /* occupy 2 column tracks from wherever it lands */
}

/* Spanning rows too */
.card--tall {
  grid-row: span 2;     /* occupy 2 row tracks */
}

/* Explicit positioning: place a panel in column 3-5, row 1-2 */
.sidebar {
  grid-column: 3 / 5;
  grid-row: 1 / 2;
}

Zeilennummern beginnen bei 1 für die linke/obere Kante und gehen bis n+1, wobei n die Anzahl der Spuren ist. Negative Zeilennummern zählen von rechts/unten: grid-column: 1 / -1 streckt ein Element über die volle Breite des Grids, unabhängig davon, wie viele Spalten vorhanden sind — ein nützlicher Trick für Elemente voller Breite in einem mehrspaltigem Container.

grid-template-areas — Das Layout benennen

Dies ist das Feature, das Grid wirklich großartig für seitenweite Layouts macht, und es ist die lesbarste API in ganz CSS. Anstatt Elemente durch Zeilennummern zu platzieren, zeichnet man das Layout als ASCII-Kunst im CSS und weist jedem Element dann zu, welchen benannten Bereich es belegt. Die grid-template-areas-Spezifikation erfordert, dass jede Zeile die gleiche Anzahl von Zellen hat und jeder benannte Bereich rechteckig sein muss — keine L-Formen.

css
/* Full page layout: header, sidebar, main, footer */
.page-shell {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 60px 1fr 50px;
  grid-template-areas:
    "header  header"
    "sidebar main"
    "footer  footer";
  min-height: 100vh;
  gap: 0;
}

.page-header  { grid-area: header; }
.page-sidebar { grid-area: sidebar; }
.page-main    { grid-area: main; }
.page-footer  { grid-area: footer; }
html
<div class="page-shell">
  <header class="page-header">Site header / nav</header>
  <nav class="page-sidebar">Sidebar navigation</nav>
  <main class="page-main">Primary content</main>
  <footer class="page-footer">Footer</footer>
</div>

Ein Punkt (.) im Template-String lässt eine Zelle absichtlich leer. Man kann auch denselben Namen über mehrere Zellen strecken — genau das macht "header header" oben. Wenn man das Layout für verschiedene Ansichten anpasst oder umstrukturiert, aktualisiert man den Template-String an einer Stelle, anstatt über mehrere grid-column-Deklarationen zu suchen.

auto-fill vs auto-fit mit minmax()

Das Muster hinter responsiven Grids ohne Media Queries ist einer der praktischsten Tricks von Grid: repeat(auto-fill, minmax(250px, 1fr)). Aufgeschlüsselt — minmax(250px, 1fr) besagt, dass jede Spalte mindestens 250px breit sein, aber verfügbaren Platz ausfüllen soll. auto-fill weist Grid an, so viele Spalten zu erstellen, wie in den Container passen. Das Ergebnis ist ein Grid, das beim Ändern des Viewports automatisch Spalten hinzugewinnt und verliert.

css
/* Product card grid — reflows automatically, no media queries */
.product-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 1.5rem;
}

/* auto-fit collapses empty tracks — items stretch to fill the container */
.product-grid--stretch {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1.5rem;
}

Der Unterschied zwischen auto-fill und auto-fit ist subtil, spielt aber eine Rolle, wenn es weniger Elemente als Spalten gibt. Bei auto-fill reserviert Grid Platz für potenzielle Spuren, auch wenn diese leer sind — Elemente bleiben bei ihrer Mindestbreite. Bei auto-fit fallen leere Spuren auf null zusammen und Elemente dehnen sich aus, um die Zeile zu füllen. Für Produktgrids und Galerien, bei denen Elemente verfügbaren Platz nutzen sollen, sieht auto-fit üblicherweise besser aus. Für Grids, bei denen eine konsistente Elementbreite wichtiger ist als das Füllen des Containers, ist auto-fill die richtige Wahl.

Hinweis zur Browserunterstützung: auto-fill und auto-fit mit minmax() haben ausgezeichnete Unterstützung — 97%+ weltweit laut caniuse. Man kann dieses Muster heute ohne Fallback in jedem modernen Projekt verwenden.

Ausrichtung in Grid

Grid verwendet dasselbe Box-Alignment-Modul wie Flexbox, sodass die Eigenschaftsnamen direkt zugeordnet werden, wenn man Flexbox bereits kennt. Das wichtigste mentale Modell: justify wirkt auf die Inline-Achse (horizontal in den meisten Schreibmodi), align wirkt auf die Block-Achse (vertikal).

  • justify-items / align-items — Standardausrichtung für alle Elemente in ihrer Grid-Zelle. Standard ist stretch, weshalb Grid-Elemente automatisch ihre Zelle ausfüllen.
  • justify-content / align-content — verteilt die Spuren selbst innerhalb des Containers, wenn das Grid kleiner als der Container ist (ähnlich wie Flexbox justify-content am Flex-Container).
  • justify-self / align-self — überschreibt die Ausrichtung für ein einzelnes Element. Nützlich, wenn ein Element zentriert werden muss, während andere sich strecken.
  • Werte: start, end, center, stretch, space-between, space-around, space-evenly (letzte drei nur für *-content).
css
/* Center all card content within its cell */
.card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  align-items: start;     /* cards align to their cell top, not stretched */
  gap: 1.5rem;
}

/* Center a single call-to-action card both ways */
.card--cta {
  justify-self: center;
  align-self: center;
}

/* Distribute tracks with space between — useful for nav bars */
.nav-grid {
  display: grid;
  grid-template-columns: auto auto auto;
  justify-content: space-between;
}

Bei einem Wechsel von Flexbox ist der Hauptunterschied, dass die Grid-Ausrichtung auf einem zweidimensionalen Raum wirkt — man kann beide Achsen gleichzeitig steuern. In Flexbox gilt die Querachsenausrichtung für eine gesamte Zeile oder Spalte von Elementen; in Grid hat jedes Element seine eigene Zelle, sodass justify-self und align-self eine elementweise Kontrolle ermöglichen, ohne Wrapper-Elemente zu benötigen.

Echtes Layout: Vollständige Dashboard-Shell

Hier ist eine vollständige CSS-Grid-Seitenstruktur für eine Dashboard-Anwendung — Header, einklappbare Navigationsleiste, Hauptinhaltsbereich mit eigenem internen Grid und Footer. Dies ist das Muster, das man als äußerste Layout-Shell für ein SaaS-Dashboard oder Admin-Panel verwenden würde.

css
/* ── Dashboard shell ──────────────────────────────────── */
.dashboard-shell {
  display: grid;
  grid-template-columns: 220px 1fr;
  grid-template-rows: 56px 1fr 44px;
  grid-template-areas:
    "topbar  topbar"
    "sidenav content"
    "sidenav footer";
  min-height: 100vh;
}

.dashboard-topbar  { grid-area: topbar;  background: #1e293b; }
.dashboard-sidenav { grid-area: sidenav; background: #0f172a; overflow-y: auto; }
.dashboard-content { grid-area: content; padding: 1.5rem; overflow-y: auto; }
.dashboard-footer  { grid-area: footer;  background: #f8fafc; border-top: 1px solid #e2e8f0; }

/* ── Collapsed sidebar variant ────────────────────────── */
.dashboard-shell--collapsed {
  grid-template-columns: 56px 1fr;
}

/* ── Content area — internal card grid ─────────────────── */
.dashboard-content {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  grid-template-rows: auto;
  align-content: start;
  gap: 1.25rem;
}

/* Stat cards take one column each; the main chart spans all */
.stat-card  { /* auto-placed, one column */ }
.main-chart { grid-column: 1 / -1; }   /* always full width */

/* ── Responsive: collapse to single-column on small screens */
@media (max-width: 768px) {
  .dashboard-shell {
    grid-template-columns: 1fr;
    grid-template-rows: 56px 1fr auto 44px;
    grid-template-areas:
      "topbar"
      "content"
      "sidenav"
      "footer";
  }
}
html
<div class="dashboard-shell">
  <header class="dashboard-topbar">
    <a href="/dashboard" class="brand">AppName</a>
    <nav class="topbar-actions">
      <button class="btn-icon" aria-label="Notifications">
        <span class="icon-bell"></span>
      </button>
      <img src="/avatar/user.png" class="user-avatar" alt="User menu">
    </nav>
  </header>

  <nav class="dashboard-sidenav">
    <ul>
      <li><a href="/dashboard">Overview</a></li>
      <li><a href="/dashboard/analytics">Analytics</a></li>
      <li><a href="/dashboard/users">Users</a></li>
      <li><a href="/dashboard/settings">Settings</a></li>
    </ul>
  </nav>

  <main class="dashboard-content">
    <div class="stat-card">Monthly Revenue</div>
    <div class="stat-card">Active Users</div>
    <div class="stat-card">Churn Rate</div>
    <div class="main-chart">Revenue Chart (full width)</div>
  </main>

  <footer class="dashboard-footer">
    <p>AppName v2.4.1 &mdash; <a href="/status">System Status</a></p>
  </footer>
</div>

Ein paar Dinge, die in diesem Beispiel erwähnenswert sind. Der Footer wird in der sidenav-Spalte auf großen Bildschirmen durch die Template-Area-Definition platziert, was ihn visuell vom Haupt-Scrollbereich trennt. Das 1fr bei Zeilen und overflow-y: auto im Content-Bereich bedeutet, dass der Inhaltsbereich unabhängig scrollt — Topbar und Sidenav bleiben fest an ihrem Platz, was die Standard-Dashboard-UX ist. Die @media-Abfrage unten ordnet die Grid-Areas für Mobilgeräte neu an, ohne das HTML zu berühren.

Zusammenfassung

CSS Grids Lernkurve ergibt sich hauptsächlich aus der Benennung — Linien, Spuren, Areas, fr-Einheiten — aber sobald das Modell klick macht, ist es bemerkenswert direkt. Für echte Layouts: grid-template-areas für Seitenschalen verwenden (es liest sich wie ein Wireframe), repeat(auto-fit, minmax()) für responsive Kartengrids, und explizites grid-column: span N für Elemente, die den Standardfluss brechen. Man braucht nicht die gesamte Grid-API für 90% der echten Arbeit — diese Muster decken das meiste davon ab.

Für weitere Lektüre: der CSS-Tricks Complete Guide to Grid ist die beste einseitige Referenz; die MDN CSS Grid-Dokumentation geht tief in jede Eigenschaft; und die W3C CSS Grid Level 1 Spezifikation ist überraschend lesbar, wenn man das genaue Verhalten von Grenzfällen verstehen möchte. Die Browserkompatibilität ist ausgezeichnet — prüfe caniuse.com/css-grid für aktuelle Zahlen. Wenn du an einem Live-Projekt arbeitest und dein CSS aufräumen möchtest, wird der CSS-Formatter auf dieser Seite deine Stylesheets ordnen und verschönern.