Cheat Sheet

CSS Layout Cheat Sheet

A practical reference for the two layout systems that replaced floats and tables: Flexbox and CSS Grid. Property-by-property breakdowns first, then copy-paste recipes for the layouts you reach for most.

Flexbox and Grid are the two modern CSS layout modules, and both are defined in specifications rather than as browser conveniences. Flexbox handles one dimension at a time. Items flow along a main axis, and the engine then distributes any leftover space between, around, or inside them. Grid handles two dimensions at once, so you can declare column and row tracks before any content exists and place items into both, even when the container size is unknown. That is why a flex row feels natural for a toolbar, while a page skeleton with a sidebar and a footer reads more clearly as a grid. The tables below follow the property names used in the MDN references linked at the end of this page.

A quick rule of thumb: use Flexbox for content that flows on one line, use Grid for regions that must line up in both axes at once.

Flexbox

One-dimensional layout: items flow along a single main axis and wrap onto new lines.

Every property in the Flexbox tables maps onto one small conceptual model. flex-direction chooses the main axis, and the cross axis runs perpendicular to it, so row and column are the same system seen from a different angle. Free space is the raw material the layout engine works with. flex-grow stretches items to consume leftover space, flex-shrink lets items give up size when the container tightens, and flex-basis sets the starting size before either runs. The shorthand flex: 1 expands to 1 1 0%, which is why equal-width children are so easy to achieve. One trap is worth remembering: flex items default to a minimum size of auto, meaning a long word can force a narrow column wider than its flex-basis until you set min-width: 0 on the item. Both behaviors are spelled out in the flexible box layout reference maintained by MDN.

Reach for Flexbox when the group itself is one-dimensional: nav bars, button rows, label plus input pairings, or an avatar beside a paragraph of text.

Container properties

set on display: flex
PropertyCommon valuesWhat it does
displayflex | inline-flexTurns the element into a flex container; its direct children become flex items.
flex-directionrow | row-reverse | column | column-reverseSets the main axis along which items are laid out.
flex-wrapnowrap | wrap | wrap-reverseControls whether items wrap onto new lines when they overflow the container.
flex-flow<flex-direction> <flex-wrap>Shorthand that combines flex-direction and flex-wrap in one declaration.
justify-contentflex-start | flex-end | center | space-between | space-around | space-evenlyDistributes items along the main axis.
align-itemsstretch | flex-start | flex-end | center | baselineAligns items along the cross axis within a single line.
align-contentflex-start | flex-end | center | space-between | space-around | stretchAligns wrapped lines on the cross axis; only takes effect with multiple lines.
gap<length>Sets the space between items on both axes.
row-gap<length>Sets the space between flex lines.
column-gap<length>Sets the space between items within a line.
place-content<align-content> <justify-content>Shorthand for align-content and justify-content together.

Item properties

set on the flex children
PropertyCommon valuesWhat it does
flex-grow<number>How much the item grows to fill available free space on the main axis.
flex-shrink<number>How much the item shrinks when there is not enough room.
flex-basisauto | <length> | <percentage>Initial main-axis size before flex-grow and flex-shrink are applied.
flex<grow> <shrink> <basis>Shorthand for the three values above; flex: 1 equals 1 1 0%.
align-selfauto | flex-start | flex-end | center | baseline | stretchOverrides align-items for this single item.
order<integer>Changes the visual order of the item without touching the DOM.

CSS Grid

Two-dimensional layout: items are placed into rows and columns at the same time.

Grid separates the structure of the container from the placement of its content. grid-template-columns and grid-template-rows declare explicit tracks, and inside those tracks the fr unit shares leftover space proportionally while minmax() lets a single track flex between a floor and a ceiling. Items that are never placed explicitly fall into implicit tracks, whose sizes you control with grid-auto-rows and grid-auto-columns instead of leaving them to chance. grid-template-areas turns the skeleton into readable ASCII art, which is exactly how the holy grail recipe below expresses its regions. Alignment reuses the box alignment vocabulary from Flexbox: place-items: center centers everything in one declaration, and align-content or justify-content move the whole grid when it is narrower than its container.

Choose Grid when alignment has to hold in two axes at once, such as card galleries, dashboards, and full page skeletons.

Container properties

set on display: grid
PropertyCommon valuesWhat it does
displaygrid | inline-gridTurns the element into a grid container.
grid-template-columnsnone | <track>…Defines column tracks, e.g. 1fr 2fr or repeat(3, 1fr).
grid-template-rowsnone | <track>…Defines row tracks.
grid-template-areas<string>+Names regions using ASCII-art strings for grid-area placement.
grid-templatenone | <rows> / <columns>Shorthand for template rows, columns and areas.
gap<row-gap> <column-gap>Space between rows and columns; grid-gap is the legacy alias.
row-gap<length>Space between rows.
column-gap<length>Space between columns.
justify-itemsstart | end | center | stretchAligns items horizontally within their grid area.
align-itemsstart | end | center | stretch | baselineAligns items vertically within their grid area.
place-items<align-items> <justify-items>Shorthand for both; place-items: center centers everything.
justify-contentstart | end | center | stretch | space-between | space-around | space-evenlyDistributes the whole grid along the row axis when it is narrower than the container.
align-contentstart | end | center | stretch | space-between | space-around | space-evenlyDistributes the whole grid along the column axis.
place-content<align-content> <justify-content>Shorthand for both content distributions.
grid-auto-flowrow | column | denseControls placement order for auto-placed items; dense backfills holes.
grid-auto-rows<track-size>Default height for implicitly-created rows.
grid-auto-columns<track-size>Default width for implicitly-created columns.

Item properties

set on the grid children
PropertyCommon valuesWhat it does
grid-columngrid-column-start / grid-column-endPlaces an item across columns, e.g. 1 / 3 or span 2.
grid-rowgrid-row-start / grid-row-endPlaces an item across rows.
grid-area<name> | row-start / col-start / row-end / col-endAssigns the item to a named area or sets all four lines at once.
justify-selfstart | end | center | stretchOverrides justify-items for this single item.
align-selfstart | end | center | stretch | baselineOverrides align-items for this single item.
place-self<align-self> <justify-self>Shorthand for both self alignments.

Layout recipes

Copy-paste patterns for the most common layouts. Click Copy to grab the full snippet.

Each recipe below is deliberately minimal. Copy the snippet, adjust the sizes and breakpoints, and keep the property model from the tables above in mind.

Perfect centering

Center any child both horizontally and vertically. The grid version needs just one line; the flexbox alternative is equally common.

/* Grid: shortest way */
.center {
  display: grid;
  place-items: center;
  min-height: 100vh;
}

/* Flexbox alternative */
.center-flex {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}

Holy grail layout

Classic header / nav / main / aside / footer with a fluid center column. grid-template-areas makes the skeleton readable.

.holy-grail {
  display: grid;
  grid-template-columns: 220px 1fr 220px;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header header"
    "nav    main   aside"
    "footer footer footer";
  min-height: 100vh;
  gap: 1rem;
}
.holy-grail > header { grid-area: header; }
.holy-grail > nav    { grid-area: nav; }
.holy-grail > main   { grid-area: main; }
.holy-grail > aside  { grid-area: aside; }
.holy-grail > footer { grid-area: footer; }

Responsive equal-width cards

Auto-fitting columns that wrap on their own: each card is at least 220px wide and stretches to fill the last row. No media queries needed.

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem;
}

Sticky footer

Make a short page still push the footer to the bottom of the viewport. flex: 1 lets the main area absorb all leftover space.

.app {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
.app > main { flex: 1; }

Media object

Icon/avatar next to a fluid text block. The body grows to fill the row while the media stays fixed.

.media {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
}
.media > .media-body { flex: 1; }

Three mistakes cover most layout bugs you will see in real projects. The first is mixing up justify-content with align-items, and the fix is to name the axis first, main or cross, before picking the property. The second is forgetting the auto minimum size of flex items, so a sidebar with a long label overflows its flex-basis until min-width: 0 appears on the item. The third is letting grid content spill into unexpected implicit rows because no grid-auto-rows was set, so tracks snap to whatever the content demands instead of the rhythm you designed. All three behaviors follow from the way the specifications define free space and track sizing, not from browser quirks.

A useful habit before writing any alignment property: state which axis you mean first, out loud.

Grid and Flexbox are not the only layout tools, and the older ones still have honest jobs. Floats remain the right answer for wrapping an image into surrounding text. Inline-block produces rows of boxes but brings the whitespace gap between elements along with it. CSS multi-column layout, driven by column-count and column-width, flows long text into newspaper-style columns with no track definitions at all. And display: contents removes a wrapper element from the layout box tree entirely, which is useful when a semantic container should not become a box. Start with these when a single-line problem does not need a full layout module.

Reordering content is an accessibility decision, not just a visual one. Both order and grid-auto-flow: dense change only the rendered sequence, while keyboard focus and screen readers still walk the DOM order.

WCAG 2.2 requires meaningful reading sequences and logical focus order, which is why the recipes above keep the DOM in the same order as the layout. If you reorder cards for a visual effect, move the elements in the markup and reserve visual reordering for cases where the reading order truly does not matter.

The Flexbox and Grid specification references behind this cheat sheet

Each link below documents the standard or reference that supports the properties and recipes on this page.

  • MDN, CSS flexible box layout The basis for every Flexbox container and item row above, including the main and cross axis model and the flex grow, shrink and basis algorithm behind flex: 1.
  • MDN, CSS grid layout The source for the Grid track, placement and alignment properties above, plus the auto-fit and minmax() behavior used by the responsive cards recipe.
  • WHATWG HTML Standard, semantics chapter Defines the header, nav, main, aside and footer elements that the holy grail recipe assigns to named grid areas.
  • W3C WCAG 2.2 Backs the accessibility note above about visual reordering versus DOM order for focus and reading sequence.