CSS Grid Layout
1. Grid Container Properties (display: grid)
| Property | Values | Description | Default |
|---|---|---|---|
| display | grid | inline-grid |
Creates grid container (block or inline level) | - |
| grid-template-columns | track-size ... |
Defines column tracks (widths) | none |
| grid-template-rows | track-size ... |
Defines row tracks (heights) | none |
| grid-template-areas | "area names" |
Named grid areas for item placement | none |
| grid-template | rows / columns |
Shorthand for rows, columns, areas | none |
| gap / grid-gap | row-gap column-gap |
Spacing between rows and columns | 0 |
| row-gap | length |
Spacing between rows | 0 |
| column-gap | length |
Spacing between columns | 0 |
| justify-items | start | center | end | stretch |
Align items horizontally within cells | stretch |
| align-items | start | center | end | stretch |
Align items vertically within cells | stretch |
| place-items | align justify |
Shorthand for align-items and justify-items | stretch |
| justify-content | start | center | end | space-between | space-around | space-evenly |
Align entire grid horizontally in container | start |
| align-content | start | center | end | space-between | space-around | space-evenly |
Align entire grid vertically in container | start |
| place-content | align justify |
Shorthand for align-content and justify-content | start |
| grid-auto-columns | track-size |
Size of implicit columns (auto-created) | auto |
| grid-auto-rows | track-size |
Size of implicit rows (auto-created) | auto |
| grid-auto-flow | row | column | dense |
Auto-placement algorithm direction | row |
| Track Sizing | Syntax | Description | Example |
|---|---|---|---|
| Fixed | px, rem, % |
Fixed size tracks | 200px 300px |
| fr Unit | 1fr 2fr |
Flexible fraction of available space | 1fr 2fr (1:2 ratio) |
| auto | auto |
Size based on content | auto 1fr auto |
| min-content | min-content |
Smallest possible without overflow | min-content 1fr |
| max-content | max-content |
Largest content size without wrapping | max-content 1fr |
| minmax() | minmax(min, max) |
Size range between min and max | minmax(200px, 1fr) |
| fit-content() | fit-content(limit) |
min(max-content, max(min-content, limit)) | fit-content(300px) |
| repeat() | repeat(count, tracks) |
Repeat track pattern count times | repeat(3, 1fr) |
| auto-fill | repeat(auto-fill, size) |
Creates as many tracks as fit | repeat(auto-fill, 200px) |
| auto-fit | repeat(auto-fit, size) |
Like auto-fill but collapses empty tracks | repeat(auto-fit, minmax(200px, 1fr)) |
Example: Basic grid setup
/* Simple grid - 3 equal columns */
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
/* Or shorter: */
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
}
/* Fixed and flexible columns */
.layout {
display: grid;
grid-template-columns: 250px 1fr 200px; /* Sidebar, main, aside */
grid-template-rows: auto 1fr auto; /* Header, content, footer */
gap: 20px;
min-height: 100vh;
}
/* Responsive grid with auto-fit */
.responsive-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1rem;
/* Items wrap automatically when space is insufficient */
}
Example: Track sizing functions
/* minmax() for flexible constraints */
.grid {
grid-template-columns:
minmax(200px, 300px) /* Between 200px and 300px */
minmax(0, 1fr); /* Grows but can shrink to 0 */
}
/* auto-fill vs auto-fit */
.auto-fill {
/* Creates empty tracks if space available */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
.auto-fit {
/* Collapses empty tracks, items grow to fill */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
/* Complex patterns */
.complex {
grid-template-columns:
200px /* Fixed sidebar */
repeat(3, 1fr) /* 3 equal flexible columns */
minmax(150px, 20%); /* Constrained column */
}
2. Grid Item Placement and Spanning (grid-column, grid-row)
| Property | Values | Description | Example |
|---|---|---|---|
| grid-column-start | line | span n |
Start column line number | grid-column-start: 1; |
| grid-column-end | line | span n |
End column line number | grid-column-end: 3; |
| grid-column | start / end |
Shorthand for column start and end | grid-column: 1 / 3; |
| grid-row-start | line | span n |
Start row line number | grid-row-start: 1; |
| grid-row-end | line | span n |
End row line number | grid-row-end: 4; |
| grid-row | start / end |
Shorthand for row start and end | grid-row: 1 / 4; |
| grid-area | row-start / col-start / row-end / col-end |
Shorthand for all placement properties | grid-area: 1 / 1 / 3 / 4; |
| span keyword | span n |
Span n tracks from start position | grid-column: span 2; |
| -1 (negative) | -1, -2, -3... |
Count from end (right/bottom) | grid-column: 1 / -1; |
| justify-self | start | center | end | stretch |
Horizontal alignment within cell | justify-self: center; |
| align-self | start | center | end | stretch |
Vertical alignment within cell | align-self: center; |
| place-self | align justify |
Shorthand for align-self and justify-self | place-self: center; |
Example: Item placement with line numbers
/* Grid with 3 columns, 3 rows */
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 100px);
gap: 10px;
}
/* Place item from column 1 to 3 (spans 2 columns) */
.item1 {
grid-column: 1 / 3; /* Start at line 1, end at line 3 */
grid-row: 1 / 2; /* First row */
}
/* Alternative: using span */
.item2 {
grid-column: span 2; /* Span 2 columns from auto position */
grid-row: 2;
}
/* Full row span */
.header {
grid-column: 1 / -1; /* From first to last column */
}
/* Complex placement */
.featured {
grid-column: 2 / 4; /* Columns 2-3 */
grid-row: 1 / 3; /* Rows 1-2 (spans 2 rows) */
}
Example: Spanning and negative indices
/* Span multiple columns/rows */
.wide {
grid-column: span 3; /* Span 3 columns */
}
.tall {
grid-row: span 2; /* Span 2 rows */
}
/* Negative line numbers (count from end) */
.full-width {
grid-column: 1 / -1; /* First to last column */
}
.last-column {
grid-column: -2 / -1; /* Second-to-last to last */
}
/* Shorthand grid-area */
.box {
/* row-start / col-start / row-end / col-end */
grid-area: 1 / 2 / 3 / 4;
}
/* Self-alignment */
.centered {
place-self: center; /* Center in both directions */
}
3. Grid Template Areas (grid-template-areas) and Named Lines
| Feature | Syntax | Description | Use Case |
|---|---|---|---|
| grid-template-areas | "area1 area2" "area3 area4" |
Visual ASCII-art layout definition | Semantic page layouts |
| grid-area (name) | grid-area: name; |
Assign item to named area | Place items in template areas |
| . (dot) | "header . sidebar" |
Empty cell (no content) | Gaps in layout |
| Named Lines | [name] size [name] |
Name grid lines for reference | Semantic line references |
| Line Name Syntax | grid-column: name-start / name-end; |
Reference named lines | Readable placement code |
Example: Grid template areas
/* Visual layout definition */
.page {
display: grid;
grid-template-columns: 200px 1fr 150px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
"sidebar content aside"
"footer footer footer";
gap: 1rem;
min-height: 100vh;
}
/* Assign items to areas */
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }
/* Empty cells with dot */
.layout-with-gap {
grid-template-areas:
"logo nav nav"
"main main ."
"footer footer footer";
}
Example: Named grid lines
/* Define named lines */
.grid {
display: grid;
grid-template-columns:
[main-start] 1fr
[content-start] 2fr
[content-end] 1fr
[main-end];
grid-template-rows:
[header-start] auto
[header-end content-start] 1fr
[content-end footer-start] auto
[footer-end];
}
/* Use named lines for placement */
.header {
grid-column: main-start / main-end;
grid-row: header-start / header-end;
}
.main-content {
grid-column: content-start / content-end;
grid-row: content-start / content-end;
}
/* Multiple names for same line */
.grid-multi {
grid-template-columns:
[sidebar-start] 250px
[sidebar-end main-start] 1fr
[main-end];
}
Note: Grid template areas create a visual representation of
layout in code. Named lines provide semantic meaning to grid structure. Both
improve code readability.
4. Implicit Grid Behavior and Auto-placement
| Property | Values | Description | Use Case |
|---|---|---|---|
| grid-auto-flow | row | column | dense |
Direction for auto-placed items | Control placement algorithm |
| row (default) | grid-auto-flow: row; |
Fill rows first, then create new row | Horizontal reading order |
| column | grid-auto-flow: column; |
Fill columns first, then create new column | Vertical reading order |
| dense | grid-auto-flow: row dense; |
Fill gaps with smaller items (reorder) | Masonry-like layouts |
| grid-auto-rows | size |
Size of implicitly created rows | Auto-generated row height |
| grid-auto-columns | size |
Size of implicitly created columns | Auto-generated column width |
Example: Auto-placement behavior
/* Explicit grid: 3 columns, 2 rows */
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 100px 100px;
gap: 10px;
}
/* If more than 6 items, implicit rows are created */
.grid {
grid-auto-rows: 100px; /* Size for auto-created rows */
}
/* Column flow instead of row */
.column-flow {
display: grid;
grid-template-rows: repeat(3, 100px);
grid-auto-flow: column; /* Create new columns as needed */
grid-auto-columns: 200px; /* Size of auto columns */
}
/* Dense packing (fills gaps) */
.masonry {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-flow: dense; /* Fill gaps with later items */
gap: 10px;
}
.item-large {
grid-column: span 2; /* Takes 2 columns */
}
Example: Implicit vs explicit tracks
/* Explicit: defined tracks */
.grid {
display: grid;
grid-template-columns: 200px 1fr 200px; /* 3 explicit columns */
grid-template-rows: auto 1fr; /* 2 explicit rows */
/* Implicit: auto-created when items overflow */
grid-auto-rows: minmax(100px, auto); /* Auto rows grow with content */
grid-auto-columns: 200px; /* Auto columns fixed */
}
/* Items beyond explicit grid create implicit tracks */
.item {
grid-column: 1; /* Uses explicit column */
}
.item-overflow {
grid-column: 5; /* Creates implicit columns 4 and 5 */
}
/* Auto-fit with implicit rows */
.responsive {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-auto-rows: 200px; /* All rows (implicit) are 200px */
}
Warning:
grid-auto-flow: dense can change visual
order from DOM order, which may confuse screen readers and keyboard navigation. Use carefully for
accessibility.
5. Subgrid Implementation and Use Cases NEW
| Feature | Syntax | Description | Use Case |
|---|---|---|---|
| subgrid | grid-template-columns: subgrid; |
Inherits parent's column tracks | Nested grids aligned to parent |
| subgrid rows | grid-template-rows: subgrid; |
Inherits parent's row tracks | Vertical alignment across nested items |
| Both axes | grid-template: subgrid / subgrid; |
Inherits both rows and columns | Complete parent grid alignment |
| Named lines | Inherited from parent | Subgrid can use parent's named lines | Semantic line references |
Example: Subgrid basics
/* Parent grid */
.parent {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1rem;
}
/* Child item spans multiple columns and becomes subgrid */
.child-grid {
grid-column: span 4; /* Spans all 4 parent columns */
display: grid;
grid-template-columns: subgrid; /* Inherits 4 columns from parent */
gap: 0.5rem; /* Can override gap */
}
/* Grandchildren align to parent grid */
.grandchild {
/* Automatically placed in parent's column tracks */
}
/* Practical: Card with aligned content */
.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
}
.card {
display: grid;
grid-template-rows: subgrid; /* Align card sections vertically */
grid-row: span 3; /* Card spans 3 rows: image, title, description */
}
Example: Subgrid for consistent alignment
/* Product cards with aligned prices */
.products {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
grid-auto-rows: auto auto auto 1fr auto; /* image, title, desc, spacer, price */
gap: 1rem;
}
.product-card {
display: grid;
grid-template-rows: subgrid; /* Inherit parent's 5 rows */
grid-row: span 5; /* Span all 5 rows */
border: 1px solid #ddd;
padding: 1rem;
}
/* All cards' prices align horizontally */
.product-image { grid-row: 1; }
.product-title { grid-row: 2; }
.product-desc { grid-row: 3; }
.product-price { grid-row: 5; } /* Always at same height */
/* Form with label/input alignment */
.form {
display: grid;
grid-template-columns: [labels] 150px [inputs] 1fr;
gap: 1rem;
}
.form-row {
display: grid;
grid-template-columns: subgrid; /* Inherit label/input columns */
grid-column: 1 / -1; /* Span all columns */
}
Note: Subgrid enables alignment across nesting levels. Nested
grid items can align with parent grid tracks. Browser support: Firefox 71+, Safari
16+, Chrome 117+
6. CSS Grid vs Flexbox - When to Use Which
| Criteria | Use Flexbox | Use Grid | Reason |
|---|---|---|---|
| Dimension | 1-dimensional (row OR column) | 2-dimensional (rows AND columns) | Grid handles both axes simultaneously |
| Content-driven | ✓ Items control layout | ✗ Container controls layout | Flexbox better for variable content sizes |
| Layout-driven | ✗ Content-first approach | ✓ Structure-first approach | Grid better for defined layouts |
| Wrapping | Limited control (flex-wrap) | Full control (grid-auto-flow, areas) | Grid provides precise wrapping control |
| Alignment | Single axis at a time | Both axes independently | Grid aligns items in both directions |
| Gap control | Simple gap property | Row-gap and column-gap separately | Grid offers more granular spacing |
| Browser Support | Excellent (IE10+ with prefixes) | Good (IE11+ with prefixes, limited) | Flexbox has wider legacy support |
| Overlapping | Not native (needs absolute positioning) | Native (grid items can overlap) | Grid naturally supports overlays |
| Use Case | Best Choice | Why | Alternative |
|---|---|---|---|
| Navigation bar | Flexbox | 1D horizontal layout, variable content | Grid works but overkill |
| Page layout | Grid | 2D structure (header, sidebar, content, footer) | Flexbox requires nesting |
| Card grid | Grid | Equal heights, precise columns/rows | Flexbox with wrapping works |
| Button group | Flexbox | Content-driven sizing, simple alignment | Grid is more complex |
| Form layout | Grid | Label/input alignment, multiple rows | Flexbox needs nesting |
| Media object | Flexbox | Image + text, simple horizontal layout | Grid works but simpler with Flex |
| Image gallery | Grid | Precise rows/columns, equal sizing | Flexbox can work with wrap |
| Centering | Either | Both excellent for centering | Flexbox slightly simpler |
| Dashboard | Grid | Complex 2D layout, overlapping panels | Flexbox too complex |
| Responsive columns | Grid | auto-fit/auto-fill, precise control | Flexbox with calc() more complex |
Example: When to combine both
/* Grid for page structure */
.page {
display: grid;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
grid-template-columns: 250px 1fr;
}
/* Flexbox for navigation inside header */
.header {
display: flex;
justify-content: space-between;
align-items: center;
}
/* Grid for card layout */
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1rem;
}
/* Flexbox for card content */
.card {
display: flex;
flex-direction: column;
}
.card-footer {
margin-top: auto; /* Push to bottom with flexbox */
}
Grid Best Practices
- Use fr units for flexible, proportional sizing
- Use repeat(auto-fit, minmax(...)) for responsive grids without media queries
- Use grid-template-areas for readable, semantic layouts
- Use gap instead of margins for consistent spacing
- Use
grid-column: 1 / -1to span full width - Use minmax() to constrain track sizes while maintaining flexibility
- Use subgrid to align nested grids with parent tracks
- Combine Grid for page structure, Flexbox for component layout
- Use Grid for 2D layouts, Flexbox for 1D layouts