Inden CSS Grid betød opbygning af et ordentligt sidelayout floats, clearfixes, negative margener og en bøn om, at kolonnerne ikke kollapsede. Flexbox hjalp, men det er fundamentalt éndimensionelt — du får en række eller en kolonne, ikke begge. CSS Grid er det første layoutsystem, der er hjemmehørende i CSS og faktisk er designet til todimensionelle layouts. Udfordringen er ikke browserunderstøttelse — den har været universel siden 2017. Udfordringen er, at API'et har et stort overfladeareal, og navngivningen er inkonsekvent nok til at være forvirrende, hvis du ikke har den underliggende model klar. Denne artikel fokuserer på de dele, du vil bruge i rigtigt arbejde.
Rækker, kolonner og gittercontaineren
Alt begynder med display: grid på containeren. Når det er indstillet, bliver direkte børn automatisk gitterelementer — ingen klasse er nødvendig på dem. Du definerer kolonne- og rækkespor med grid-template-columns og grid-template-rows.
Den vigtigste enhed at forstå først er fr — brokenhedsenheden. Den repræsenterer en brøkdel af den tilgængelige plads i gittercontaineren, efter at spor med fast størrelse er taget i betragtning. Én 1fr betyder "tag én andel af det resterende rum." To kolonner af 1fr 1fr betyder lige halvdele. 2fr 1fr betyder, at den første kolonne får dobbelt så meget som den anden. Det er den enhed, der gør flydende gitre naturlige.
/* 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) er en stenografi, så du ikke behøver at skrive den samme sporsstørrelse fem gange. Det virker også med blandede værdier: repeat(3, 1fr 2fr) giver dig et 6-kolonne-gitter med skiftende smalle og brede spor. For rækker er auto næsten altid det, du vil have — rækker dimensionerer sig efter deres indhold, medmindre du eksplicit har brug for en fast højde.
<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>gap-egenskaben
Inden Grid betød tilføjelse af mellemrum mellem layoutbørn margener — og margener betød at huske at nulstille det sidste barn, håndtere kollaps og tilføje negative margener på containeren for at kompensere. gap løser dette rent. Det tilføjer plads kun mellem spor, aldrig på de ydre kanter af gitteret.
/* 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;
}gap virker også i Flexbox (det erstattede det gamle grid-gap-alias). Hvis du allerede bruger Flexbox til en komponent og blot har brug for afstand mellem elementer, kan du bruge gap der også uden at skifte til Grid.Eksplicit placering af elementer
Som standard flyder gitterelementer ind i den næste tilgængelige celle i kildrækkefølge. Men Grids virkelige styrke er, at du kan placere elementer hvor som helst — og endda få dem til at spænde over flere spor. Egenskaberne er grid-column og grid-row, som refererer til gitterlinjer (linjerne mellem spor, nummereret fra 1).
/* Dashboard hvor det første kort spænder over 2 kolonner */
.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;
}Linjenumre starter ved 1 for venstre/topkant og går op til n+1, hvor n er antallet af spor. Negative linjenumre tæller fra højre/bunden: grid-column: 1 / -1 strækker et element over hele bredden af gitteret uanset antallet af kolonner — et nyttigt trick til helbredselementer inde i en flerkolonne-container.
grid-template-areas — navngiv dit layout
Det er den funktion, der gør Grid genuint fantastisk til sidelayout, og det er den mest læsbare API i hele CSS. I stedet for at placere elementer med linjenumre tegner du layoutet som ASCII-kunst i CSS og fortæller derefter hvert element, hvilket navngivet område det optager. grid-template-areas-specifikationen kræver, at hver række har det samme antal celler, og hvert navngivet område skal være rektangulært — ingen L-former.
/* 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; }<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>Et punktum (.) i skabelonstrengen efterlader en celle bevidst tom. Du kan også stable det samme navn på tværs af flere celler for at spænde over dem — det er præcis det, "header header" gør ovenfor. Når du ændrer størrelse på eller omstrukturerer layoutet for forskellige visningspunkter, opdaterer du skabelonstrengen ét sted i stedet for at jage gennem flere grid-column-erklæringer.
auto-fill vs auto-fit med minmax()
Mønsteret bag responsive gitre uden medieforespørgsler er et af Grids mest praktiske tricks: repeat(auto-fill, minmax(250px, 1fr)). Nedbryd det — minmax(250px, 1fr) siger, at hver kolonne skal være mindst 250px bred, men udvide sig for at fylde tilgængeligt rum. auto-fill fortæller Grid at oprette så mange kolonner, som der kan passe i containeren givet den begrænsning. Resultatet er et gitter, der automatisk vinder og taber kolonner, efterhånden som visningsporten ændres.
/* 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;
}Forskellen mellem auto-fill og auto-fit er subtil, men betyder noget, når der er færre elementer end kolonner. Med auto-fill reserverer Grid plads til de potentielle spor selv om de er tomme — elementer forbliver ved deres minimumbredde. Med auto-fit kollapser tomme spor til nul, og elementerne udvides for at fylde rækken. Til produktgitre og gallerier, hvor du vil have elementer til at bruge tilgængeligt rum, ser auto-fit normalt bedre ud. Til gitre, hvor konsistent elementbredde er vigtigere, er auto-fill det rigtige valg.
auto-fill og auto-fit med minmax() har fremragende understøttelse — 97%+ globalt ifølge caniuse. Du kan bruge dette mønster i dag uden en fallback i ethvert moderne projekt.Justering i Grid
Grid bruger den samme Box Alignment-modul som Flexbox, så egenskabsnavnene mappes direkte, hvis du allerede kender Flexbox. Den mentale nøglemodel: justify opererer på inline-aksen (vandret i de fleste skrivningstilstande), align opererer på blokaksen (lodret).
justify-items/align-items— standardjustering for alle elementer inden for deres gittercelle. Standard erstretch, hvilket er grunden til, at gitterelementer automatisk fylder deres celle.justify-content/align-content— distribuerer sporene selv inden for containeren, når gitteret er mindre end containeren (ligner Flexboxjustify-contentpå flex-containeren).justify-self/align-self— tilsidesætter justering for et enkelt element. Nyttigt, når et element skal centreres, mens andre strækkes.- Værdier:
start,end,center,stretch,space-between,space-around,space-evenly(de tre sidste kun for*-content).
/* 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;
}Hvis du kommer fra Flexbox, er den vigtigste forskel, at Grid-justering opererer i et todimensionelt rum — du kan styre begge akser simultant. I Flexbox gælder tværaksen-justering en hel række eller kolonne af elementer; i Grid har hvert element sin egen celle, så justify-self og align-self giver dig per-element-kontrol uden brug for wrapper-elementer.
Rigtigt layout: komplet dashboard-skal
Her er en komplet CSS Grid-sidestruktur til en dashboard-applikation — sidehoved, sammenklappelig nav-sidebjælke, hovedindholdsområde med sit eget interne gitter og sidefod. Dette er det mønster, du ville bruge som det yderste layoutskal til et SaaS-dashboard eller adminpanel.
/* ── 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";
}
}<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 — <a href="/status">System Status</a></p>
</footer>
</div>Et par ting værd at bemærke i dette eksempel. Sidefoden er placeret i sidenav-kolonnen på store skærme ved hjælp af skabelonområdedefinitionen, hvilket holder den visuelt adskilt fra det rullende hovedindholdsområde. 1fr på rækker og overflow-y: auto på indholdspanelet betyder, at indholdsområdet ruller uafhængigt — topbjælken og sidenavigationen forbliver på plads, hvilket er standard dashboard-UX. @media-forespørgslen nedenfor omarrangerer gitterområderne til mobil uden at røre HTML overhovedet.
Opsummering
CSS Grids indlæringskurve kommer mest fra navngivningen — linjer, spor, områder, fr-enheder — men når modellen klikker, er det bemærkelsesværdigt direkte. Til rigtige layouts: brug grid-template-areas til sideskal (det læses som en wireframe), brug repeat(auto-fit, minmax()) til responsive kortgitre, og brug eksplicit grid-column: span N til elementer, der bryder det normale flow. Du behøver ikke hele Grids API til 90% af rigtige arbejde — disse mønstre dækker det meste.
Til videre læsning: CSS-Tricks komplette guide til Grid er den bedste enkeltsidesreference; MDN's CSS Grid-dokumentation går dybt ind i hver egenskab; og W3C CSS Grid Level 1-specifikationen er overraskende læsbar, hvis du vil forstå den præcise adfærd ved kanttilfælde. Browserkompatibilitet er fremragende — tjek caniuse.com/css-grid for aktuelle tal. Hvis du arbejder på et levende projekt og vil rydde op i din CSS, vil CSS-formateren på dette websted rydde op og forskønne dine stilark.