CSS Grid - Two-Dimensional Flexible Layouts

What You'll Learn

  • Create grids with display: grid
  • Define columns and rows with grid-template-columns and grid-template-rows
  • Use the fr unit for flexible tracks
  • Create responsive grids with repeat(), auto-fit, and minmax()
  • Name and place items with grid-template-areas
  • Control spacing with gap, row-gap, and column-gap
  • Span items across tracks with grid-column and grid-row
  • Align grid items and the grid itself with alignment properties

Introduction to CSS Grid

CSS Grid is a two-dimensional layout system that excels at creating complex layouts with both rows and columns simultaneously. Unlike Flexbox (which works in one dimension), Grid allows you to control both axes at once, making it perfect for page layouts, card grids, dashboards, and any interface requiring precise two-dimensional control.

Apply display: grid to a container to make its direct children grid items, then define your grid structure using template properties.

display: grid - Creating a Grid Container

Transform an element into a grid container with display: grid. By default, items stack in a single column, but you control the layout with template properties.

/* Create grid container */ .container { display: grid; } /* All direct children become grid items */ /* Inline grid container */ .inline-grid { display: inline-grid; } /* Container behaves as inline element, children are grid items */ /* Simple 3-column grid */ .three-columns { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 1rem; }

grid-template-columns & rows - Defining Tracks

Define the structure of your grid by specifying column and row sizes with grid-template-columns and grid-template-rows.

/* Fixed sizes */ grid-template-columns: 200px 400px 200px; /* Three columns: 200px, 400px, 200px */ /* Flexible units (fr) */ grid-template-columns: 1fr 2fr 1fr; /* Three columns: first and third equal, middle is twice as wide */ /* Mixed units */ grid-template-columns: 200px 1fr 1fr; /* Fixed first column, two flexible columns */ /* Explicit rows */ grid-template-rows: 100px auto 100px; /* Header 100px, content auto-sized, footer 100px */ /* Practical examples */ /* Three equal columns */ .grid-equal { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 1rem; } /* Sidebar + main layout */ .layout { display: grid; grid-template-columns: 250px 1fr; grid-template-rows: auto 1fr auto; gap: 1rem; min-height: 100vh; } /* Dashboard grid */ .dashboard { display: grid; grid-template-columns: 200px 1fr 1fr; grid-template-rows: 80px 1fr 1fr; gap: 1.5rem; }

repeat() - DRY Grid Tracks

The repeat() function eliminates repetition when defining multiple same-sized tracks.

/* Without repeat */ grid-template-columns: 1fr 1fr 1fr 1fr 1fr; /* With repeat */ grid-template-columns: repeat(5, 1fr); /* Same result, much cleaner */ /* Repeat patterns */ grid-template-columns: repeat(3, 100px 200px); /* Creates: 100px 200px 100px 200px 100px 200px */ /* Mixed with other tracks */ grid-template-columns: 200px repeat(3, 1fr) 200px; /* Fixed sidebars with flexible middle */ /* Practical examples */ /* 12-column grid system */ .grid-12 { display: grid; grid-template-columns: repeat(12, 1fr); gap: 1rem; } /* Equal-height card grid */ .cards { display: grid; grid-template-columns: repeat(4, 1fr); gap: 2rem; } /* Photo gallery */ .gallery { display: grid; grid-template-columns: repeat(6, 1fr); gap: 0.5rem; }

auto-fit, auto-fill & minmax() - Responsive Grids

Create automatically responsive grids without media queries using auto-fit, auto-fill, and minmax().

/* auto-fit: Fit items, collapse empty tracks */ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); /* Items at least 200px, grow to fill space */ /* auto-fill: Fill space, keep empty tracks */ grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); /* Creates as many tracks as fit, even if empty */ /* minmax(): Define minimum and maximum sizes */ grid-template-columns: repeat(3, minmax(150px, 1fr)); /* Each column: min 150px, max equal share */ /* Practical examples */ /* Responsive card grid */ .cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 2rem; } /* Cards wrap automatically as viewport shrinks */ /* Image gallery */ .gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1rem; } /* Fills all available space with images */ /* Product grid */ .products { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1.5rem; } /* Responsive without media queries! */ .responsive-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); gap: 1rem; } /* Never smaller than container, max 300px before wrapping */

grid-template-areas - Named Grid Areas

Create semantic, visual grid layouts with named areas using grid-template-areas. This provides the most readable way to define complex layouts.

/* Define layout with names */ .layout { display: grid; grid-template-columns: 200px 1fr 200px; grid-template-rows: auto 1fr auto; grid-template-areas: "header header header" "sidebar main aside" "footer footer footer"; gap: 1rem; } /* Assign elements to areas */ .header { grid-area: header; } .sidebar { grid-area: sidebar; } .main { grid-area: main; } .aside { grid-area: aside; } .footer { grid-area: footer; } /* Practical examples */ /* Blog layout */ .blog { display: grid; grid-template-columns: 1fr 3fr 1fr; grid-template-areas: "header header header" "nav article aside" "footer footer footer"; gap: 2rem; min-height: 100vh; } /* Dashboard */ .dashboard { display: grid; grid-template-columns: 250px 1fr 1fr; grid-template-rows: 80px 1fr 1fr 60px; grid-template-areas: "sidebar header header" "sidebar main main" "sidebar stats stats" "sidebar footer footer"; } /* App shell */ .app { display: grid; grid-template-columns: auto 1fr; grid-template-rows: auto 1fr; grid-template-areas: "sidebar toolbar" "sidebar content"; height: 100vh; } /* Responsive: Stack on mobile */ @media (max-width: 768px) { .layout { grid-template-columns: 1fr; grid-template-areas: "header" "main" "sidebar" "aside" "footer"; } }

gap - Spacing Between Tracks

The gap property creates spacing between grid tracks (rows and columns) without adding margins to items.

/* Single value: same gap in all directions */ gap: 1rem; /* Two values: row-gap column-gap */ gap: 1rem 2rem; /* Individual properties */ row-gap: 1rem; column-gap: 2rem; /* Practical examples */ /* Card grid with spacing */ .cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2rem; } /* Dense layout */ .gallery { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 0.5rem; } /* Spacious dashboard */ .dashboard { display: grid; grid-template-columns: 250px 1fr 1fr; gap: 1.5rem 2rem; /* 1.5rem between rows, 2rem between columns */ } /* Form layout */ .form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }

grid-column & grid-row - Spanning Tracks

Make grid items span multiple columns or rows using grid-column and grid-row.

/* Span syntax */ grid-column: span 2; /* Spans 2 columns */ grid-row: span 3; /* Spans 3 rows */ /* Line-based placement */ grid-column: 1 / 3; /* Start at line 1, end at line 3 (spans 2 columns) */ grid-row: 2 / 5; /* Start at line 2, end at line 5 (spans 3 rows) */ /* Shorthand */ grid-column: 1 / -1; /* Span from first to last column */ grid-row: 2 / span 2; /* Start at row 2, span 2 rows */ /* Practical examples */ /* Featured card */ .card-featured { grid-column: span 2; grid-row: span 2; } /* Full-width header */ .header { grid-column: 1 / -1; } /* Sidebar spanning multiple rows */ .sidebar { grid-row: 1 / -1; } /* Complex magazine layout */ .magazine { display: grid; grid-template-columns: repeat(6, 1fr); gap: 1rem; } .hero { grid-column: 1 / 4; grid-row: 1 / 3; } .feature { grid-column: 4 / 7; grid-row: 1 / 2; } .article { grid-column: span 2; } /* Masonry-style grid */ .item-tall { grid-row: span 2; } .item-wide { grid-column: span 2; } .item-large { grid-column: span 2; grid-row: span 2; }

Grid Alignment - justify, align, place

Control how grid items align within their cells and how the grid itself aligns within its container.

/* Align items within their cells */ /* Horizontal alignment (inline axis) */ justify-items: start; /* Left align */ justify-items: center; /* Center horizontally */ justify-items: end; /* Right align */ justify-items: stretch; /* Fill width (default) */ /* Vertical alignment (block axis) */ align-items: start; /* Top align */ align-items: center; /* Center vertically */ align-items: end; /* Bottom align */ align-items: stretch; /* Fill height (default) */ /* Shorthand for both */ place-items: center; /* Same as: align-items: center; justify-items: center; */ /* Align the grid itself within container */ /* Horizontal grid alignment */ justify-content: start; justify-content: center; justify-content: end; justify-content: space-between; justify-content: space-around; justify-content: space-evenly; /* Vertical grid alignment */ align-content: start; align-content: center; align-content: end; align-content: space-between; /* Individual item overrides */ .item { justify-self: center; /* Override justify-items */ align-self: end; /* Override align-items */ place-self: center; /* Override both */ } /* Practical examples */ /* Center all grid items */ .centered-grid { display: grid; grid-template-columns: repeat(3, 100px); place-items: center; gap: 2rem; } /* Center grid in container */ .container { display: grid; grid-template-columns: repeat(3, 200px); justify-content: center; min-height: 100vh; } /* Dashboard tiles */ .dashboard { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); place-items: center; gap: 1rem; } /* Profile card */ .profile { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 1rem; }

Key Takeaways

  • Two-dimensional: Grid controls rows AND columns simultaneously, unlike one-dimensional Flexbox
  • display: grid: Turns element into grid container; direct children become grid items
  • grid-template-columns/rows: Define track sizes with px, %, fr, auto, or mixed units
  • fr unit: Flexible unit representing a fraction of available space; better than % for grids
  • repeat(): Eliminates repetition: repeat(3, 1fr) = 1fr 1fr 1fr
  • auto-fit + minmax(): Creates responsive grids without media queries
  • auto-fit vs auto-fill: auto-fit collapses empty tracks; auto-fill preserves them
  • grid-template-areas: Create semantic, visual layouts with named areas
  • gap: Spacing between tracks; cleaner than margins (no edge spacing)
  • grid-column/row: Span multiple tracks with span N or line numbers
  • 1 / -1: Span from first to last line (full width or height)
  • place-items: Shorthand for justify-items + align-items (item alignment)
  • place-content: Shorthand for justify-content + align-content (grid alignment)
  • Grid lines: Numbered from 1; negative numbers count from end