TechEarl

How to Center Anything in CSS (Flexbox, Grid, and place-items)

Center a div in CSS the modern way: flexbox justify-content + align-items, the grid place-items one-liner, margin:auto, and absolute + transform. Which method to reach for, and the gotchas with each.

Ishan Karunaratne⏱️ 8 min readUpdated
Share thisCopied
Center anything in CSS: flexbox justify-content and align-items, the grid place-items center one-liner, margin auto, and absolute positioning with transform, plus when each applies.

The fastest way to center one box inside another, both horizontally and vertically, is two lines of grid:

css
.parent {
  display: grid;
  place-items: center;
}

That centers any direct child on both axes, with no fixed widths, no negative margins, no math. It is Baseline (supported in every current browser since 2020), so you can ship it today without prefixes or fallbacks. The rest of this page is the full menu: the flexbox version everyone reaches for, when margin: auto is the right tool, the absolute-position method for overlays, and the difference between centering text and centering a box. Pick the one that matches your situation, because "center a div" has about five correct answers depending on what you are centering and into what.

The grid one-liner: place-items: center

place-items is shorthand for align-items (the block/cross axis) plus justify-items (the inline axis). Setting it to center on a grid container centers every direct child in both directions:

css
.hero {
  display: grid;
  place-items: center;
  min-height: 100vh;
}
html
<div class="hero">
  <div class="card">Perfectly centered</div>
</div>

This is my default for "one thing in the middle of a region" because it does not care about the child's size, it works when the child wraps to multiple lines, and there is nothing to keep in sync. The one thing to know: place-items aligns items inside their grid area, so if you have multiple children they all stack into the same cell and center individually. For one centered element it is the cleanest option there is.

Flexbox: justify-content + align-items

The flexbox version is the one most people already know. On a row-direction flex container, justify-content aligns along the main (horizontal) axis and align-items aligns along the cross (vertical) axis:

css
.parent {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}

That is the workhorse. It does the same job as the grid one-liner and is worth reaching for when the surrounding layout is already flex, or when you want the centered items laid out in a row or column with gap between them:

css
.toolbar {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 1rem;
}

gap in flexbox is Baseline now, so you no longer need margins between flex children. The axis mapping is the part that trips people up: if you switch to flex-direction: column, the axes swap, justify-content now controls vertical and align-items controls horizontal. The full breakdown of axes, flex-grow, and wrapping lives in my practical guide to flexbox; this page is just the centering slice.

Centering a single item with margin: auto

Inside a flex (or grid) container, margin: auto on a child absorbs all the free space around it on both axes, which centers that one item without touching the parent's alignment properties:

css
.parent {
  display: flex;
}
.child {
  margin: auto;
}

This is genuinely useful when you want to center one item while siblings stay put, or push one item to an edge. margin-left: auto on a single flex child shoves it to the right and pulls everything else left, which is the idiomatic "logo on the left, menu on the right" navbar pattern, no spacer div required.

For block-level boxes outside flex or grid, the classic margin: 0 auto still centers horizontally, but only if the element has a width less than its container:

css
.container {
  max-width: 60rem;
  margin: 0 auto;
}

margin: 0 auto does nothing vertically on a normal block element (auto top/bottom margins resolve to zero in normal flow). That is the reason "center vertically" needs flexbox, grid, or the transform method below, not just margins.

Absolute positioning with transform

When the centered element is taken out of flow, an overlay, a modal, a tooltip, a badge pinned to a card, the classic technique is to offset by 50% then pull back by half the element's own size with transform:

css
.overlay {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

The top/left of 50% positions the element's top-left corner at the center of the positioned ancestor; the translate(-50%, -50%) then shifts it back by half its own width and height, landing the element's center on the center. It works without knowing the element's dimensions, which is why it survived as the go-to for so long.

Two caveats. The parent needs position: relative (or any non-static position) or the element will center against the viewport instead. And translating by a non-integer pixel can land the box on a half-pixel and render text slightly blurry; if you see fuzzy edges, nudge with transform: translate(-50%, -50%) translateZ(0) or prefer the grid/flex method, which snaps to the pixel grid. For an overlay that genuinely needs to escape flow this is still the right tool; for in-flow content, grid or flex is cleaner.

Centering text vs centering a box

These are different problems and need different properties. To center the text inside an element, use text-align:

css
.headline {
  text-align: center;
}

text-align: center centers inline content (text, inline images, inline-block buttons) inside the box. It does nothing to the box itself. For a single line of text that also needs vertical centering inside a fixed-height element, line-height equal to the height is the old trick:

css
.badge {
  height: 3rem;
  line-height: 3rem;
  text-align: center;
}

That only works for a single line; the moment text wraps, line-height breaks. For multi-line text centered vertically, go back to flexbox or grid on the container. The rule of thumb: text-align and line-height center content within a box, while flex, grid, margin, and transform center the box within its parent.

Which method to reach for

css
/* One item centered both ways, you control the parent: grid */
.parent { display: grid; place-items: center; }

/* Same, but the layout is already flex or you want gap between items */
.parent { display: flex; justify-content: center; align-items: center; }

/* Center one child, leave siblings alone, or push one to an edge */
.child { margin: auto; }            /* or margin-left: auto to push right */

/* Horizontal-only, a fixed-width block in normal flow */
.container { max-width: 60rem; margin: 0 auto; }

/* The element is out of flow (overlay, modal, pinned badge) */
.overlay { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }

/* Center the text inside an element, not the element */
.text { text-align: center; }

If you are sizing the centered region with mixed units (a header offset, viewport math), CSS calc() with min(), max(), and clamp() pairs naturally with any of these for fluid layout. And once you are comfortable centering, the :has() parent selector opens up conditional centering, for example styling a container differently when it contains a centered media element.

FAQ

See also

Sources

Authoritative references this article was fact-checked against.

TagsCSSflexboxCSS gridplace-itemscenter divvertical alignlayout

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years building software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Currently Chief Technology Officer at a healthcare tech startup, which is where most of these field notes come from.

Keep reading

Related posts

How to Archive Files Matching a find Pattern with tar

find locates the files, tar archives them. The safe pairing is find -print0 piped into tar reading a NUL-delimited list from stdin: no breakage on spaces or newlines. The flag breakdown, the macOS BSD tar vs GNU tar difference, the -exec append alternative, archiving by modification time, and the compression choices.

How to Use Regex in Nginx (location and rewrite)

Use regex in Nginx with location blocks and the rewrite directive: how location modifiers and matching priority work, why return beats rewrite for redirects, and copy-paste config for HTTPS, www, trailing slashes, 301s, clean URLs, and access blocking.