CSS Grid Layout: A Practical Introduction

CSS Grid became available in all major browsers in 2017, making it the first native two-dimensional layout system in CSS. Unlike Flexbox (which is one-dimensional — either a row or a column), Grid lets you control both axes at once — perfect for full page layouts and complex card grids.

Problem: How do you build two-dimensional layouts in CSS — controlling both rows and columns — without relying on floats or JavaScript?

Solution: Use CSS Grid — declare display: grid on a container, then control columns and rows with grid-template-columns, grid-template-rows, and grid-template-areas. It handles both axes at once, unlike Flexbox.

A basic responsive grid with auto-fill columns:

.card-grid {
    display: grid;
    grid-template-columns: repeat( auto-fill, minmax( 280px, 1fr ) );
    gap: 1.5rem;
}

.card-grid .card {
    background: #fff;
    border-radius: 4px;
    padding: 1.5rem;
    box-shadow: 0 2px 6px rgba(0,0,0,.08);
}

A classic 12-column grid with named areas:

.page-layout {
    display: grid;
    grid-template-columns: 1fr 3fr 1fr;
    grid-template-rows: auto 1fr auto;
    grid-template-areas:
        "header  header  header"
        "sidebar content aside"
        "footer  footer  footer";
    min-height: 100vh;
}

.site-header  { grid-area: header; }
.site-sidebar { grid-area: sidebar; }
.site-content { grid-area: content; }
.site-aside   { grid-area: aside; }
.site-footer  { grid-area: footer; }

@media ( max-width: 768px ) {
    .page-layout {
        grid-template-columns: 1fr;
        grid-template-areas:
            "header"
            "content"
            "sidebar"
            "aside"
            "footer";
    }
}

Spanning items across columns or rows:

.featured-card {
    grid-column: span 2; /* occupies 2 columns */
    grid-row:    span 2; /* occupies 2 rows */
}

NOTE: auto-fill and auto-fit behave differently when there are fewer items than columns: auto-fill keeps the empty tracks, auto-fit collapses them. Use auto-fit when you want the items to stretch to fill the container on sparse rows.