CSS Flexbox & Grid
Stop guessing at layout. The properties that actually center, distribute, and arrange things — flexbox for one dimension, grid for two.
Flexbox and grid are layout modes you switch on for a container with display; its direct children become flex or grid items. Flexbox lays items along one axis and sizes them from their content outward. Grid defines rows and columns first, then places items into the cells.
In flexbox, justify-* works along the main axis (set by flex-direction) and align-* across it. In grid, justify-* is always the row direction and align-* the column direction. Most real layouts use both: grid for the page, flex inside its pieces.
Flexbox (one axis)
- Turn on
display: flex· direction:flex-direction: row | column- Along main axis
justify-content: center | space-between | space-around | flex-start- Across cross axis
align-items: center | stretch | flex-start | baseline- Wrap
flex-wrap: wrap· shorthandflex-flow: row wrap- Item grow/shrink
flex: 1(grow) ·flex: 0 0 200px(fixed basis)- Gap
gap: 1rem— spacing without margins- flex-direction: column
- the main axis turns vertical, so
justify-contentnow aligns top to bottom - align-content: center
- spaces the lines of a wrapping container — no effect without
flex-wrap: wrap - display: inline-flex
- flex inside, inline outside — an icon-and-label button sitting in a line of text
Flex items
- flex: 1
- means
1 1 0%: items share the space equally, whatever their content - flex: auto
- means
1 1 auto: grow from content size, so bigger content gets more room - flex: none
- means
0 0 auto: never grow or shrink - flex: 2 vs flex: 1
- widths split 2:1; bare
flex-grow: 2splits only the leftover space 2:1 - flex-shrink: 0
- stop an icon, avatar or sidebar from being squeezed narrower
- min-width: 0
- let an item shrink below its content — the fix for overflowing text, tables and
pre - margin-left: auto
- push this item, and everything after it, to the far end
- align-self: flex-end
- override
align-itemsfor one item - flex-basis: 200px
- starting size along the main axis; beats
widthwhen both are set - order: -1
- reorders visually only — tab and screen-reader order still follow the HTML
Grid (two axes)
- Turn on
display: grid- Columns
grid-template-columns: 1fr 2fr· repeat:repeat(3, 1fr)- Responsive columns
repeat(auto-fit, minmax(200px, 1fr))— the famous one- Gaps
gap: 1rem·row-gap/column-gap- Span cells
grid-column: span 2·grid-row: 1 / 3- Named areas
grid-template-areas: "hd hd" "sb mn"thengrid-area: hd- fr
- a share of the space left over after fixed and content-sized tracks
- minmax(0, 1fr)
- a
1frallowed below its content — stops one long word or table widening the column - auto-fill vs auto-fit
- fill keeps empty tracks; fit collapses them, so the items stretch across the row
- minmax(min(200px, 100%), 1fr)
- the responsive pattern that also survives containers narrower than 200px
Grid placement & alignment
- grid-column: 1 / -1
- span from the first line to the last — a full-width row in the explicit grid
- grid-auto-rows: minmax(100px, auto)
- size for rows the grid creates on its own: at least 100px, taller if needed
- grid-auto-flow: dense
- backfill holes left by wide items — visual order then drifts from the HTML
- grid-template-rows: subgrid
- a nested grid reuses its parent’s tracks, so content lines up across cards
- justify-items / align-items
- position every item inside its cell;
justify-self/align-selffor one - place-content: center
- center the whole set of tracks inside a larger grid container
- "hd hd" ". mn"
- in
grid-template-areasa.is an empty cell; every area must be a rectangle
Centering (the eternal question)
- Center anything (flex)
display:flex; justify-content:center; align-items:center- Center anything (grid)
display:grid; place-items:center- Center a block
margin-inline: autowith a set width- margin: auto (in flex or grid)
- centers a child on both axes inside a flex or grid parent
- inset: 0; margin: auto
- centers an absolutely positioned box that has a width and height
- text-align: center
- centers inline content such as text and inline-blocks, not the block itself
Which one?
- Flex
- Content in a single row or column — navbars, toolbars, button rows.
- Grid
- Two-dimensional layouts — page skeletons, card galleries, forms.
- Both
- Grid for the page, flex inside each cell. They compose.
- Content out vs layout in
- flex sizes from the content outward; grid sets the tracks first, then fills them
- gap, not margins
gapworks in flex and grid and never doubles up or leaks at the edges
Recipes
Page layout: header, sidebar, main, footer
.page {
display: grid;
grid-template-columns: 220px minmax(0, 1fr);
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"nav main"
"footer footer";
min-height: 100vh;
}
header { grid-area: header; }
nav { grid-area: nav; }
main { grid-area: main; }
footer { grid-area: footer; }
@media (max-width: 700px) {
.page {
grid-template-columns: 1fr;
grid-template-areas: "header" "nav" "main" "footer";
}
}The 1fr row pushes the footer to the bottom of short pages. minmax(0, 1fr) keeps a wide table or code block from widening the main column — give that child overflow-x: auto so it scrolls in place.
Responsive card grid with no media queries
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
gap: 1rem;
}Columns appear and disappear as the container resizes, and min(240px, 100%) stops a card overflowing a container narrower than 240px. Use auto-fill if a lone card should stay card-sized instead of stretching.
Navbar: logo left, links right, everything centered vertically
.nav {
display: flex;
align-items: center;
gap: 1rem;
}
.nav .logo { margin-right: auto; } /* pushes everything after it to the right */
.nav .avatar { flex-shrink: 0; } /* never squash the avatar */An auto margin absorbs all the free space on its side, so no spacer elements are needed. Add flex-wrap: wrap if the links should drop to a second line on small screens.
Media object that never overflows
.media {
display: flex;
gap: 12px;
align-items: flex-start;
}
.media img { flex: none; width: 48px; height: 48px; }
.media .body {
flex: 1;
min-width: 0; /* allow shrinking below the longest word */
}
.media .body p { overflow-wrap: anywhere; }Without min-width: 0 a flex item cannot shrink below its content, so one long URL pushes the text off the screen. To truncate a single line instead, use white-space: nowrap; overflow: hidden; text-overflow: ellipsis.
Line up titles and buttons across cards (subgrid)
.cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
}
.card {
display: grid;
grid-row: span 3; /* title, body, button */
grid-template-rows: subgrid; /* share the parent's row tracks */
}Every card’s title, body and button now share row heights, so the buttons align even when one card has more text. Subgrid works in all current major browsers.
Questions about CSS Flexbox & Grid Cheat Sheet
When should I use flexbox vs grid?
Use flexbox when items flow in one direction and their size should come from their content: navigation bars, toolbars, a row of buttons, an icon next to a label, or a list that wraps. Use grid when you want to control rows and columns together, so things line up in both directions: page layouts, card galleries, forms with aligned labels, dashboards. A useful test is whether you are laying out content, which suits flex, or a structure that content goes into, which suits grid. They nest freely, and most pages use grid for the overall layout and flexbox inside the components.
What is the difference between auto-fill and auto-fit in CSS grid?
Both create as many columns as fit when used in repeat() with minmax(), such as repeat(auto-fill, minmax(200px, 1fr)). The difference only appears when there are fewer items than columns. auto-fill keeps the empty column tracks, so the existing items stay at their minimum size and leave blank space at the end of the row. auto-fit collapses the empty tracks to zero, so the existing items stretch to fill the whole row. Choose auto-fit when a few items should fill the space, and auto-fill when cards should keep a consistent size.
Why is my flex item overflowing its container?
Flex items default to min-width: auto, which means they refuse to shrink below the width of their content. A long URL, a wide table, a pre block or an image with a fixed width therefore pushes the item, and the page, wider than the container. Set min-width: 0 on the flex item, or overflow: hidden, to let it shrink, and then deal with the content itself using overflow-wrap: anywhere, text-overflow: ellipsis or overflow-x: auto. The same issue appears in grid as a 1fr column blowing out, and minmax(0, 1fr) fixes it.
How do I center a div horizontally and vertically?
The shortest modern way is to make the parent a grid and center its content: display: grid together with place-items: center. With flexbox, set display: flex, justify-content: center and align-items: center on the parent. Either way, the parent needs a height for vertical centering to be visible, such as min-height: 100vh for a full-screen layout. Inside a flex or grid parent, margin: auto on the child also centers it on both axes. To center only horizontally, a block with a set width can use margin-inline: auto.