CSS Grid Auto Placement Algorithm
What Is Grid Auto Placement?
When you define a grid container but do not explicitly place every item using grid-column or grid-row, the browser must decide where those unplaced items go. The auto placement algorithm handles this — it fills empty cells following rules you control via grid-auto-flow.
Understanding this algorithm helps you predict layout behavior instead of guessing and tweaking blindly.
The Three Modes of grid-auto-flow
| Value | Behavior | Use Case |
|---|---|---|
row (default) | Fill rows left to right, then move to next row | Standard card grids, lists |
column | Fill columns top to bottom, then move to next column | Vertical feeds, sidebar items |
dense | Backfill earlier gaps left by spanning items | Masonry-like layouts, mixed-size grids |
You can combine dense with row or column:
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-flow: row dense;
}
How the Algorithm Works — Step by Step
Step 1: Place Items with Explicit Positions
Items that specify grid-column or grid-row get placed first. The algorithm skips these and reserves their cells.
.featured {
grid-column: 1 / 3; /* spans 2 columns */
}
Step 2: Determine the Auto-Flow Direction
The algorithm picks the next available cell based on grid-auto-flow:
- row: Move right across columns, then down to next row
- column: Move down across rows, then right to next column
Step 3: Place Remaining Items in Order
Items without explicit placement fill cells in DOM order. If an item spans multiple tracks (span 2), the algorithm searches for a contiguous block of empty cells large enough.
Step 4: Handle Dense Packing (if enabled)
With dense, after placing an item that spans multiple tracks, the algorithm goes back to check whether smaller items can fill gaps left behind. Without dense, those gaps stay empty.
The Spanning Problem
Spanning items create gaps. Consider a 4-column grid with grid-auto-flow: row:
[1-wide] [1-wide] [1-wide] [3-wide spanning]
┌─────────────────┐
│ spans 3 cols │
└─────────────────┘
The 3-wide item does not fit in the last column of row 1 (needs 3 consecutive empty cells), so it wraps to row 2. This leaves column 4 of row 1 empty — a gap.
Without dense: the gap persists. The next item starts at row 2, column 1.
With dense: the algorithm backfills. The next 1-wide item fills column 4 of row 1.
/* Without dense — gaps persist */
.grid { grid-auto-flow: row; }
/* With dense — gaps get filled */
.grid { grid-auto-flow: row dense; }
Practical Example: Magazine Layout
.magazine {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: minmax(200px, auto);
grid-auto-flow: row dense;
gap: 16px;
}
.hero {
grid-column: span 2;
grid-row: span 2;
}
.sidebar {
grid-column: span 1;
grid-row: span 2;
}
Without dense, the hero item (2×2) and sidebar item (1×2) would leave scattered gaps. With dense, smaller items slide into those gaps, creating a compact layout.
Dense Packing Trade-offs
| Aspect | row (sparse) | row dense |
|---|---|---|
| Visual gaps | Possible | Minimized |
| DOM order preserved | Yes | No — smaller items may appear before larger ones in DOM |
| Accessibility | Predictable tab order | Tab order may jump visually |
| Performance | Faster algorithm | Slightly slower (backfilling) |
Important: dense reorders items visually but not in the DOM. Screen readers and keyboard navigation still follow DOM order. If visual order matters for accessibility, use explicit placement instead.
Auto Tracks and Implicit Grid
When items overflow the defined grid-template-columns or grid-template-rows, the browser creates implicit tracks. Control their size with:
.grid {
grid-auto-rows: minmax(100px, auto);
grid-auto-columns: 200px;
}
Without these, implicit tracks default to auto — sized to their content. This often creates uneven row heights in dynamic layouts.
Named Grid Lines and Auto Placement
If you define named lines, the algorithm can use them for automatic spanning:
.grid {
grid-template-columns: [col-start] 1fr [col-end] repeat(3, 1fr);
}
.item {
grid-column: col-start / span 2;
}
Named lines make auto placement more predictable because items reference specific tracks rather than numeric indexes that shift when you change column counts.
Key Takeaways
- Grid auto placement fills unplaced items according to
grid-auto-flow - Spanning items can leave gaps —
densebackfills those gaps - Dense packing trades DOM order preservation for visual compactness
- Always define
grid-auto-rowswhen row count is dynamic - For accessible layouts, prefer explicit placement over
densereordering
Try It Yourself
Build and experiment with grid layouts using our CSS Grid Generator. Define columns, rows, and gaps visually — then copy the CSS into your project.