Go Back

CSS Grid Layout

Definition

CSS Grid Layout (commonly called "Grid") is a two-dimensional layout system designed for creating complex, grid-based user interfaces. Unlike one-dimensional layout methods like Flexbox that control either rows OR columns, Grid allows developers to control both rows AND columns simultaneously, enabling precise placement and alignment of elements in a web page.

Introduced as a formal specification in 2017, CSS Grid represents one of the most powerful layout systems available in CSS. It allows developers to create layouts that were previously only possible with more complex CSS and JavaScript combinations, or that relied on table-based layouts (which mix content with presentation).

With CSS Grid, the layout is separate from the HTML structure, allowing for visual rearrangement without changing the underlying markup—a key advantage for accessibility and responsive design.

Core Concepts

Grid Container and Grid Items

A CSS Grid layout consists of:

  1. Grid Container: The element with display: grid or display: inline-grid applied
  2. Grid Items: The direct children of the grid container
  3. Grid Lines: The horizontal and vertical dividing lines that create the grid structure
  4. Grid Tracks: The rows and columns that make up the grid
  5. Grid Cells: The smallest units in the grid, formed by intersecting rows and columns
  6. Grid Areas: Named regions that can span multiple grid cells
<div class="grid-container">
  <div class="grid-item">Item 1</div>
  <div class="grid-item">Item 2</div>
  <div class="grid-item">Item 3</div>
  <div class="grid-item">Item 4</div>
  <div class="grid-item">Item 5</div>
  <div class="grid-item">Item 6</div>
</div>
.grid-container {
  display: grid;
  grid-template-columns: 200px 1fr 1fr;
  grid-template-rows: auto auto;
  gap: 20px;
}

Grid Lines and Line Numbering

Grid lines are automatically numbered, starting from 1 for both rows and columns:

1    2    3    4
 ┌────┬────┬────┐  1
 │    │    │    │
 ├────┼────┼────┤  2
 │    │    │    │
 └────┴────┴────┘  3

Grid items can be positioned by referring to these line numbers:

.grid-item:first-child {
  grid-column: 1 / 3; /* From column line 1 to 3 (spans 2 columns) */
  grid-row: 1 / 2;    /* From row line 1 to 2 (spans 1 row) */
}

Container Properties

Creating a Grid

To create a grid container:

.container {
  display: grid; /* or display: inline-grid */
}

Defining Grid Structure

Grid Template Columns and Rows

Set the tracks (columns and rows) of the grid:

.grid-container {
  /* Three columns: 100px wide, 1 fraction of space, 2 fractions of space */
  grid-template-columns: 100px 1fr 2fr;
  
  /* Two rows: auto height, 100px height */
  grid-template-rows: auto 100px;
}

Using the repeat() Function

For repeated patterns:

.grid-container {
  /* 12-column grid with equal widths */
  grid-template-columns: repeat(12, 1fr);
  
  /* Alternating pattern: 100px, then 1fr, repeated 3 times */
  grid-template-columns: repeat(3, 100px 1fr);
}

minmax() Function

For responsive grid tracks that have minimum and maximum sizes:

.grid-container {
  /* Columns that are at least 200px wide but can expand to 1fr */
  grid-template-columns: repeat(3, minmax(200px, 1fr));
  
  /* Rows that are at least 100px tall but can expand as needed */
  grid-template-rows: minmax(100px, auto);
}

Using auto-fill and auto-fit

Create responsive grids with dynamic number of columns:

.responsive-grid {
  /* Creates as many 200px columns as will fit */
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  
  /* Similar to auto-fill but collapses empty tracks */
  /* grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); */
}

Grid Gaps

Create spacing between grid items:

.grid-container {
  column-gap: 20px;    /* Space between columns */
  row-gap: 10px;       /* Space between rows */
  gap: 10px 20px;      /* Shorthand: row-gap column-gap */
  gap: 15px;           /* Equal gap in both directions */
}

Grid Template Areas

Define named grid areas for semantic layout:

.page-layout {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas: 
    "header header"
    "sidebar content"
    "footer footer";
}

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

Use a period (.) to define an empty cell:

.grid-container {
  grid-template-areas:
    "header header header"
    "sidebar content ."
    "footer footer footer";
}

Alignment Properties

Align Items in their Cells

.grid-container {
  /* Horizontal alignment within each cell */
  justify-items: start;    /* Align to left edge */
  /* justify-items: end;      Align to right edge */
  /* justify-items: center;   Align to center */
  /* justify-items: stretch;  Fill cell width (default) */
  
  /* Vertical alignment within each cell */
  align-items: start;      /* Align to top */
  /* align-items: end;        Align to bottom */
  /* align-items: center;     Align to middle */
  /* align-items: stretch;    Fill cell height (default) */
  
  /* Shorthand for both properties */
  place-items: start center; /* vertical horizontal */
}

Align the Grid within its Container

.grid-container {
  height: 100vh; /* container taller than grid content */
  
  /* Horizontal alignment of entire grid */
  justify-content: start;    /* Align grid to left */
  /* justify-content: end;      Align grid to right */
  /* justify-content: center;   Center grid horizontally */
  /* justify-content: space-between; Space items with ends at edges */
  /* justify-content: space-around;  Equal space around items */
  /* justify-content: space-evenly;  Equal space between items and edges */
  
  /* Vertical alignment of entire grid */
  align-content: start;      /* Align grid to top */
  /* align-content: end;        Align grid to bottom */
  /* align-content: center;     Center grid vertically */
  /* align-content: space-between; Space rows with ends at edges */
  /* align-content: space-around;  Equal space around rows */
  /* align-content: space-evenly;  Equal space between rows and edges */
  
  /* Shorthand for both properties */
  place-content: center start; /* vertical horizontal */
}

Grid Auto Properties

Define how automatically generated tracks behave:

.grid-container {
  /* Size of automatically generated columns */
  grid-auto-columns: 100px;
  
  /* Size of automatically generated rows */
  grid-auto-rows: minmax(100px, auto);
  
  /* Flow direction for auto-placed items */
  grid-auto-flow: row;      /* Fill by row (default) */
  /* grid-auto-flow: column;   Fill by column */
  /* grid-auto-flow: dense;    Fill gaps when possible */
  /* grid-auto-flow: row dense; Combine directions */
}

Item Properties

Grid Placement

Position items using grid lines:

.grid-item {
  /* Column start/end by line number */
  grid-column-start: 1;
  grid-column-end: 3;
  
  /* Row start/end by line number */
  grid-row-start: 2;
  grid-row-end: 4;
  
  /* Shorthand for column start/end */
  grid-column: 1 / 3;
  /* grid-column: 1 / span 2; */ /* Span 2 columns from line 1 */
  
  /* Shorthand for row start/end */
  grid-row: 2 / 4;
  /* grid-row: 2 / span 2; */ /* Span 2 rows from line 2 */
  
  /* Super shorthand for both: row-start/column-start/row-end/column-end */
  grid-area: 2 / 1 / 4 / 3;
}

Negative Line Numbers

Count grid lines from the end:

.grid-item {
  /* Spans from first column to last column */
  grid-column: 1 / -1;
  
  /* Last two rows */
  grid-row: -3 / -1;
}

Self Alignment

Override container alignment for individual items:

.grid-item {
  /* Horizontal self-alignment */
  justify-self: start;    /* Left align this item */
  /* justify-self: end;      Right align this item */
  /* justify-self: center;   Center this item horizontally */
  /* justify-self: stretch;  Fill cell width (default) */
  
  /* Vertical self-alignment */
  align-self: start;      /* Top align this item */
  /* align-self: end;        Bottom align this item */
  /* align-self: center;     Center this item vertically */
  /* align-self: stretch;    Fill cell height (default) */
  
  /* Shorthand for both properties */
  place-self: center center; /* vertical horizontal */
}

Order Property

Change the visual order of grid items:

.first-visually {
  order: -1;  /* Display earlier than default items (0) */
}

.last-visually {
  order: 1;   /* Display later than default items (0) */
}

Common Grid Layout Patterns

Basic Layout Structures

Holy Grail Layout

The classic header, footer, and three-column layout:

.holy-grail {
  display: grid;
  min-height: 100vh;
  grid-template-columns: 200px 1fr 200px;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header header"
    "left content right"
    "footer footer footer";
}

.header { grid-area: header; }
.left-sidebar { grid-area: left; }
.content { grid-area: content; }
.right-sidebar { grid-area: right; }
.footer { grid-area: footer; }

/* Responsive adjustment */
@media (max-width: 768px) {
  .holy-grail {
    grid-template-columns: 1fr;
    grid-template-areas:
      "header"
      "content"
      "left"
      "right"
      "footer";
  }
}

Card Grid

Responsive card layout:

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

.featured-card {
  grid-column: span 2;
  grid-row: span 2;
}

Magazine Layout

Complex asymmetrical layout:

.magazine-layout {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(3, auto);
  gap: 20px;
}

.headline {
  grid-column: 1 / 3;
  grid-row: 1;
}

.main-image {
  grid-column: 3 / 5;
  grid-row: 1 / 3;
}

.article {
  grid-column: 1 / 3;
  grid-row: 2 / 4;
}

.sidebar {
  grid-column: 3 / 5;
  grid-row: 3;
}

Nested Grids

Grids within grids for complex layouts:

.main-grid {
  display: grid;
  grid-template-columns: 1fr 3fr;
  gap: 20px;
}

.nested-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: auto auto;
  gap: 10px;
}

Advanced Grid Techniques

Grid Auto Placement Strategies

Control how items are automatically placed:

.auto-flow-examples {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 100px;
  gap: 10px;
  
  /* Place items row by row (default) */
  grid-auto-flow: row;
  
  /* Place items column by column */
  /* grid-auto-flow: column; */
  
  /* Fill in gaps when possible */
  /* grid-auto-flow: dense; */
}

/* Some items are explicitly placed, creating gaps */
.item-1 {
  grid-column: 1;
  grid-row: 1;
}

.item-2 {
  grid-column: 3;
  grid-row: 2;
}

Subgrid (Emerging Feature)

Allow nested grids to adopt the parent grid's track sizes:

.parent-grid {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  grid-template-rows: auto auto auto;
}

.child-element {
  grid-column: 2 / span 7;
  grid-row: 2;
  
  display: grid;
  /* Use the parent's grid tracks within the area allocated to this item */
  grid-template-columns: subgrid;
  grid-template-rows: subgrid;
}

Note: Subgrid support is still limited but is being implemented in major browsers.

Grid Template with Named Lines

Add names to grid lines for more semantic placement:

.grid-with-named-lines {
  display: grid;
  grid-template-columns:
    [sidebar-start] 200px
    [sidebar-end content-start] 1fr
    [content-end];
  grid-template-rows:
    [header-start] auto
    [header-end main-start] 1fr
    [main-end footer-start] auto
    [footer-end];
}

.header {
  grid-column: sidebar-start / content-end;
  grid-row: header-start / header-end;
}

.sidebar {
  grid-column: sidebar-start / sidebar-end;
  grid-row: main-start / main-end;
}

Multi-Layered Elements with Grid

Create overlapping elements using the same grid cells:

.layered-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 100px);
}

.base-layer,
.overlay-layer {
  grid-column: 1 / 3;
  grid-row: 1 / 3;
}

.base-layer {
  z-index: 1;
  background: lightblue;
}

.overlay-layer {
  z-index: 2;
  background: rgba(255, 0, 0, 0.5);
  /* Position slightly offset for effect */
  margin: 20px 0 0 20px;
}

Browser Support and Fallbacks

Current Support

CSS Grid is supported in all modern browsers. Internet Explorer 10 and 11 had partial support with an older syntax.

Feature Detection

Use CSS @supports to provide fallbacks:

/* Fallback layout using Flexbox */
.container {
  display: flex;
  flex-wrap: wrap;
}

.item {
  flex: 1 1 300px;
  margin: 10px;
}

/* Grid layout for supporting browsers */
@supports (display: grid) {
  .container {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 20px;
    margin: 0;
  }
  
  .item {
    flex: none;
    margin: 0;
  }
}

Grid vs. Flexbox

When to Use Grid

  • Two-dimensional layouts (rows AND columns)
  • Page-level or component layouts with both row/column organization
  • When precise item placement is needed
  • For complex, asymmetrical layouts
  • When the layout design should control the content flow

When to Use Flexbox

  • One-dimensional layouts (row OR column)
  • Distributing space among items in a single dimension
  • When content should drive the layout size
  • For simple linear layouts like navigation bars or card sets
  • For components with unknown or dynamic sizes

Combining Both

Use Grid for overall page structure, Flexbox for component alignment:

.page-container {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto 1fr auto;
}

.navigation {
  grid-column: 1 / -1;
  display: flex; /* Use Flexbox within Grid area */
  justify-content: space-between;
  align-items: center;
}

.card {
  /* Card in a grid layout */
  display: flex; /* Use Flexbox for card internals */
  flex-direction: column;
}

.card-footer {
  margin-top: auto; /* Push to bottom with Flexbox */
}

Best Practices

Layout Planning

  1. Sketch your grid first: Plan your grid structure before coding
  2. Define your grid areas: Consider using named grid areas for clarity
  3. Mobile-first approach: Start with a simple grid that works on mobile, then enhance for larger screens

Grid Naming Conventions

  1. Be consistent with line names: Use a naming convention like element-start and element-end
  2. Use descriptive area names: Names like "header", "main-content", and "sidebar" versus "area1", "area2"
  3. Document complex grids: Add comments explaining the grid structure for others (or future you)

Performance Considerations

  1. Limit the number of explicitly placed items: Rely on auto-placement when possible
  2. Avoid unnecessary complexity: Don't create more tracks than needed
  3. Be cautious with grid calculations: Complex calc() expressions in grid definitions can impact performance

Accessibility Implications

  1. Maintain logical source order: The visual order should generally match the HTML order for screen readers
  2. Be cautious with reordering: Major layout changes via grid can create confusion for keyboard navigation
  3. Test with screen readers: Ensure the layout makes sense when read linearly
  • CSS Flexbox: One-dimensional layout model that complements Grid
  • Media Queries: Used with Grid to create responsive layouts
  • CSS Box Model: Foundational concept that affects how grid items are sized
  • CSS Container Queries: Emerging feature that allows styling based on a container's size rather than the viewport
  • CSS Subgrid: Emerging feature that allows nested grids to participate in the parent grid's sizing

Conclusion

CSS Grid Layout represents a revolutionary advancement in web layout technologies, providing developers with unprecedented control over two-dimensional layouts. Its row and column-based system allows for complex, responsive designs that would be difficult or impossible to achieve with earlier CSS techniques.

While Grid has a learning curve, its declarative syntax ultimately makes layouts more maintainable and adaptable. Grid excels at creating structural frameworks for entire pages or complex components, while working harmoniously with other CSS layout methods like Flexbox for the perfect balance of structure and flexibility.

As browser support continues to strengthen and features like Subgrid mature, CSS Grid will remain an essential tool in front-end development, enabling developers to create sophisticated, accessible, and responsive layouts for the modern web.