Layout

Default to Grid. Use gap, not margin. Set constraints, not fixed dimensions. Let the browser do the work.

Grid vs Flexbox

The 1D vs 2D framing is a false distinction. The real question is who controls sizing.

Grid = parent controls

The container defines tracks and places content inside them. Columns are consistent regardless of content variation. Default for most layouts — including vertical stacks.

grid gap-4grid grid-cols-3 gap-4grid place-content-center

Flex = children control

Items negotiate their own sizes based on content. Ideal when layout should follow content — tags, nav items, pill lists, wrapping rows where items should be as wide as they need to be.

flex gap-4 items-centerflex flex-wrap gap-2

Patterns

Vertical stack

grid gap-4 — the default vertical layout.

Item 1
Item 2
Item 3

Centered content

grid place-content-center — one class centers both axes.

Centered in both axes

Horizontal row

flex gap-4 items-center — content-driven sizing.

Tag
Another tag
Longer tag here

Equal columns

grid grid-cols-3 gap-4 — parent controls column widths.

Column 1
Column 2 with more content
Column 3

Responsive grid

grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6

Item 1
Item 2
Item 3
Item 4
Item 5
Item 6

Asymmetric layout

grid grid-cols-[1fr_2fr] gap-6

Sidebar (1fr)
Main content (2fr)

Wrapping row

flex flex-wrap gap-2 — items wrap naturally based on content width. This is where Flexbox shines: children control their own size.

DesignTokensTailwindCSSGridFlexboxLayoutSpacingTypographyColorElevation

Sizing

Set constraints, not fixed dimensions. Let content breathe and the layout flex.

Constraints over fixed

Use min-h- / max-w- instead of h- / w-. Fixed dimensions clip content. Constraints let it grow.

Trust browser defaults

Block elements default to width: auto which accounts for margins and padding. Don't set w-full or w-screen unless you have a concrete reason.

fit-content

w-fit sizes an element to its content. Useful for buttons, badges, and inline elements that shouldn't stretch.

I'm only as wide as my content

fr and minmax()

Use fr units in grid templates to distribute available space. Use minmax(0, 1fr) to prevent content from forcing columns wider than intended.

Container

The container-* utility centers content with responsive horizontal padding and a configurable max width. It replaces the v1 <Container> component.

Usage

<div className="container-8xl">...</div><div className="container-4xl">...</div>

Any --container-* token works: 3xs7xl (Tailwind defaults) plus 8xl (1440px).

Responsive padding

BreakpointInline padding
Default1.5rem (24px)
md (48rem)2rem (32px)
lg (64rem)3rem (48px)

Container queries

Components should respond to their parent, not the viewport. A card in a narrow sidebar needs different styling than the same card in a wide main column — but the viewport width is the same. Use @container for component-level adaptation.

Prefer container queries

Tailwind's @container class sets container-type: inline-size. Then use @sm:, @md:, @lg: etc. as container-query variants instead of sm:, md:.

{/* Responds to parent width */}
<div className="@container">
<div className="grid @sm:grid-cols-[auto_1fr]">
<img />
<div>Content</div>
</div>
</div>

Do

Respond to parent width so the component adapts regardless of where it is placed.

{/* Responds to viewport — breaks in narrow columns */}
<div className="grid md:grid-cols-[auto_1fr]">
<img />
<div>Content</div>
</div>

Don’t

Respond to the viewport — it breaks when the same component is placed in a narrow column.

Live example — same component, different containers

Both cards use the same @sm:grid-cols-[80px_1fr] breakpoint. The narrow one stacks because its container is too small. The wider one goes side-by-side.

Narrow container

Stacks vertically — container is too narrow

Wider container

Goes side-by-side — same component, more space

Media queries for page-level layout. Container queries for component-level adaptation. Use both.

Spacing scale

Based on a 4px unit. Use with gap-, p-, m-, w-, h-.

0

0px

0.5

2px

1

4px

1.5

6px

2

8px

3

12px

4

16px

5

20px

6

24px

8

32px

10

40px

12

48px

16

64px

20

80px

24

96px

Best practices

DoDon'tWhy
gap-4mb-4 on childrenGap never creates edge spacing
grid gap-4flex flex-col gap-4Grid is simpler for vertical stacks
grid place-content-centerflex items-center justify-centerOne class centers both axes
grid grid-cols-3flex with calc(33%)Grid handles equal columns natively
min-h-[200px]h-[200px]Content can grow beyond fixed height
max-w-4xlw-fullCaps width, stays responsive
minmax(0, 1fr)300px fixed columnsFixed units cause overflow on small screens