CSS: Grid Layout
Build two-dimensional layouts with rows and columns using CSS Grid.
display: grid
Adding display: grid to a container enables CSS Grid. Its direct children become grid items and are placed into rows and columns you define. Grid is two-dimensional: it controls both rows and columns at the same time, unlike Flexbox.
display: grid
CSS Grid is a two-dimensional layout system. You define the structure (rows and columns) on the container, and items fill those slots automatically or by explicit placement.
- grid container: the parent with display: grid
- grid items: the direct children of the container
- grid tracks: the rows and columns defined on the container
- grid cell: the intersection of one row and one column
- Items auto-place into cells in source order unless positioned manually
display: grid
Four items placed into a two-column grid automatically.
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
}
.item {
background: steelblue;
color: white;
padding: 20px;
border-radius: 4px;
text-align: center;
font-size: 1.2rem;
}grid-template-columns and grid-template-rows
grid-template-columns and grid-template-rows define the size of each track in the explicit grid. Each value you list creates one track.
grid-template-columns / grid-template-rows
Each space-separated value defines one column or row. You can mix units: px, %, fr, auto, in the same declaration.
- grid-template-columns: 200px 1fr: fixed 200px column, then one flexible column
- grid-template-columns: 1fr 2fr 1fr: three columns where the middle is twice as wide
- grid-template-rows: 80px auto: first row is 80px tall; second row sizes to its content
- auto: track sizes to fit its content
grid-template-columns
Three columns: fixed sidebar, flexible main, and a smaller aside.
.grid {
display: grid;
grid-template-columns: 150px 1fr 100px;
gap: 12px;
}
.item {
background: steelblue;
color: white;
padding: 16px;
border-radius: 4px;
text-align: center;
}fr Unit (Fractional Unit)
The fr unit represents a fraction of the available space in the grid container after fixed-size tracks and gaps are accounted for. It is the most common unit used with Grid.
fr unit
fr distributes the leftover space proportionally. 1fr 1fr gives two equal columns. 1fr 2fr gives the second column twice as much space.
- 1fr 1fr: two equal columns, each half the available width
- 1fr 2fr: second column is twice as wide as the first
- 1fr 1fr 1fr: three equal columns
- fr is calculated after fixed widths and gaps are subtracted
- Equivalent to flex: 1 but for grid tracks
fr unit
The middle column gets twice the space because it is 2fr.
.grid {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
gap: 10px;
}
.item { background: steelblue; color: white; padding: 16px; border-radius: 4px; text-align: center; }
.wide { background: crimson; }repeat() Notation
The repeat() function avoids repetition when defining many identical tracks. repeat(3, 1fr) is shorthand for 1fr 1fr 1fr.
repeat()
repeat(count, size) generates that many tracks of the given size. It also works with auto-fill and auto-fit to create responsive grids without media queries.
- repeat(3, 1fr): three equal columns
- repeat(4, 200px): four fixed 200px columns
- repeat(auto-fill, 150px): as many 150px columns as fit the container
- repeat(auto-fit, minmax(150px, 1fr)): responsive columns that grow to fill space
repeat(3, 1fr)
Six items laid out in three equal columns using repeat().
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
}
.item {
background: steelblue;
color: white;
padding: 20px;
border-radius: 4px;
text-align: center;
}gap, row-gap, column-gap
gap sets the space between grid tracks. You can control row and column gaps independently or use the shorthand to set both at once.
gap
gap only adds space between tracks, it does not add space on the outside edges of the grid. Use padding on the container for outer spacing.
- gap: 16px: 16px between all rows and columns
- gap: 12px 24px: 12px between rows, 24px between columns
- row-gap: 12px: gap between rows only
- column-gap: 24px: gap between columns only
- Previously called grid-gap, gap is the modern name and also works in flexbox
gap
Different row and column gaps using gap shorthand.
.grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 8px 24px; /* row-gap column-gap */
}
.item {
background: steelblue;
color: white;
padding: 16px;
border-radius: 4px;
text-align: center;
}Grid Line-Based Placement
CSS Grid is built on a system of numbered lines. Column lines run vertically and row lines run horizontally. A grid with 3 columns has 4 column lines (1, 2, 3, 4). You place items by specifying which lines they start and end at.
Grid Lines
Grid lines are numbered starting from 1. Negative numbers count from the end: -1 is the last line. Items span between a start line and an end line.
- A 3-column grid has column lines 1, 2, 3, and 4
- A 2-row grid has row lines 1, 2, and 3
- grid-column: 1 / 3: item spans from column line 1 to line 3 (covers 2 columns)
- grid-row: 1 / 2: item spans from row line 1 to line 2 (one row)
- grid-column: 1 / -1: item spans from the first to the last column line (full width)
grid-column
Header spans all three columns using grid-column: 1 / -1.
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
}
.item { background: steelblue; color: white; padding: 16px; border-radius: 4px; text-align: center; }
.header {
grid-column: 1 / -1; /* span all columns */
background: #1e293b;
}grid-column and grid-row
grid-column and grid-row are shorthands for placing items using line numbers. The span keyword lets you specify how many tracks to cover instead of an end line number.
grid-column / grid-row
Use the slash syntax (start / end) to place items precisely. span N is a convenient alternative to calculating the end line manually.
- grid-column: 2 / 4: starts at line 2, ends at line 4 (spans 2 columns)
- grid-column: span 2: starts at auto position and spans 2 columns
- grid-row: 1 / 3: starts at row line 1, ends at row line 3 (spans 2 rows)
- grid-row: span 2: spans 2 rows from auto start position
grid-column / grid-row
B spans two columns; C spans two rows using the span keyword.
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
}
.item { background: steelblue; color: white; padding: 14px; border-radius: 4px; text-align: center; }
.b { grid-column: span 2; background: crimson; }
.c { grid-row: span 2; background: seagreen; }grid-area and Named Areas
grid-template-areas lets you name regions of the grid with plain text. Each item is then assigned to a region by name using grid-area. This creates very readable layout code.
grid-template-areas
Named areas turn your CSS into a visual ASCII map of the layout. Each string is a row; each word in the string is a column. Use a dot (.) for empty cells.
- Each quoted string in grid-template-areas defines one row
- Each word inside the string is a named cell, repeat the name to span multiple cells
- grid-area: header: assigns this item to the named header region
- . (dot): represents an empty cell
- All cells of the same name must form a rectangle
grid-template-areas
A classic page layout defined with named grid areas.
.layout {
display: grid;
grid-template-columns: 160px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
gap: 10px;
min-height: 200px;
}
.header { grid-area: header; background: #1e293b; color: white; padding: 12px; border-radius: 4px; }
.sidebar { grid-area: sidebar; background: #334155; color: white; padding: 12px; border-radius: 4px; }
.main { grid-area: main; background: steelblue; color: white; padding: 12px; border-radius: 4px; }
.footer { grid-area: footer; background: #1e293b; color: white; padding: 12px; border-radius: 4px; }Auto-Placement
When you do not explicitly place grid items, the browser's auto-placement algorithm places them one by one into the next available cell, filling in order left-to-right, top-to-bottom.
Auto-Placement
Auto-placement is the default behavior. Items fill cells in source order. grid-auto-flow controls whether items fill by row (default) or by column.
- grid-auto-flow: row: items fill across rows first (default)
- grid-auto-flow: column: items fill down columns first
- grid-auto-flow: dense: browser fills gaps left by large items
- Explicitly placed items still respect their defined position; auto items fill the gaps
Auto-placement
Item 3 moves to the next row to fill around the spanning item 2.
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
}
.item { background: steelblue; color: white; padding: 14px; border-radius: 4px; text-align: center; }
.wide { grid-column: span 2; background: crimson; }auto-fit vs auto-fill
Both auto-fit and auto-fill are used inside repeat() to create as many columns as fit the container. The difference is visible when there are fewer items than available columns.
auto-fit vs auto-fill
Both create as many columns as the container can hold. auto-fill keeps empty column tracks; auto-fit collapses empty tracks so items can grow to fill the space.
- auto-fill: creates tracks even if there are no items to fill them
- auto-fit: collapses empty tracks so remaining items can stretch
- When combined with minmax(), auto-fit creates fully responsive grids without media queries
- repeat(auto-fit, minmax(200px, 1fr)): the most common responsive grid pattern
auto-fit with minmax()
Columns resize to fill the row, resize the window to see the effect.
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 12px;
}
.item {
background: steelblue;
color: white;
padding: 20px;
border-radius: 4px;
text-align: center;
}minmax() Function
minmax(min, max) defines a size range for a track. The track will be at least min wide and at most max wide. It is most useful in responsive grids.
minmax()
minmax() prevents columns from becoming too narrow on small screens or too wide on large screens. Combined with auto-fit, it removes the need for most breakpoints in grid layouts.
- minmax(200px, 1fr): column is at least 200px but grows to fill space
- minmax(0, 1fr): column can shrink to zero but grows with fr distribution
- minmax(100px, auto): at least 100px, grows to fit content
- Use minmax(0, 1fr) instead of 1fr when items have content that can overflow fr tracks
minmax()
Each column is at least 180px wide and grows to fill the row.
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 12px;
}
.item {
background: steelblue;
color: white;
padding: 20px;
border-radius: 4px;
text-align: center;
}Implicit vs Explicit Grid
The explicit grid is what you define with grid-template-columns and grid-template-rows. The implicit grid is created automatically when items overflow the defined tracks.
Implicit vs Explicit Grid
When more items exist than your explicit grid can hold, the browser creates implicit tracks to contain them. You control implicit track sizes with grid-auto-rows and grid-auto-columns.
- explicit grid: tracks defined by grid-template-columns / grid-template-rows
- implicit grid: tracks auto-created by the browser when items overflow
- grid-auto-rows: 100px: sets the height of every implicitly created row
- grid-auto-columns: sets the width of every implicitly created column
- Without grid-auto-rows, implicit rows size to fit their content
Implicit grid rows
Only 2 columns are defined. Row 2 and 3 are implicit, sized by grid-auto-rows.
.grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-auto-rows: 80px; /* implicit rows are 80px tall */
gap: 10px;
}
.item {
background: steelblue;
color: white;
padding: 10px;
border-radius: 4px;
text-align: center;
}Grid Alignment Properties
CSS Grid has its own set of alignment properties that control how the grid tracks and items are positioned within the container and within their cells.
Grid Alignment
Grid alignment uses the same justify/align naming pattern as Flexbox. The difference is that justify works on the column (inline) axis and align works on the row (block) axis.
- justify-items: aligns all items horizontally within their cell (start, end, center, stretch)
- align-items: aligns all items vertically within their cell
- justify-content: positions the entire grid horizontally in the container
- align-content: positions the entire grid vertically in the container
- justify-self / align-self: overrides alignment for a single item
Grid alignment
justify-self and align-self override cell alignment per item.
.grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 10px;
height: 200px;
align-items: stretch; /* default */
}
.item { background: steelblue; color: white; padding: 12px; border-radius: 4px; text-align: center; }
.center { justify-self: center; align-self: center; width: 80px; background: crimson; }
.end { justify-self: end; align-self: end; width: 80px; background: seagreen; }Knowledge Check
1. Which property enables CSS Grid on a container?
2. What does the fr unit represent?
3. What does repeat(3, 1fr) mean in grid-template-columns?
4. What is the difference between auto-fill and auto-fit?
5. Which property places a grid item from column line 1 to column line 3?
6. What is an implicit grid?