CSSCentering Techniques

Centering Techniques

"How do I center a div?" is the most-asked CSS question of all time, mostly because there is no single right answer — the correct technique depends on whether you are centering one axis or two, whether the content has a known size, and what else is in the container. This page walks through every reliable method, in the order you should actually reach for them.

1. Flexbox — both axes, the modern default

For centering a single child in both directions, flexbox is the shortest, most robust option. It works regardless of whether the child's size is known ahead of time.

CSS
.parent {
  display: flex;
  justify-content: center; /* horizontal */
  align-items: center;     /* vertical */
  min-height: 100vh;       /* something to center within */
}
One axis only
Need to center on just one axis? Use only the relevant property — justify-content: center alone centers horizontally in a row, and align-items: center alone centers vertically.
2. Grid — the shortest syntax

CSS Grid has a dedicated shorthand for exactly this problem: place-items. One property, two axes.

CSS
.parent {
  display: grid;
  place-items: center; /* shorthand for align-items + justify-items */
  min-height: 100vh;
}

/* Centering just one grid item among several: */
.child {
  place-self: center;
}
Prefer grid when you already use grid
If the parent is already a grid container for layout reasons, place-items: center is the least code. If it is not, and centering is the only reason you would add a container property, flexbox and grid are functionally equivalent here — pick whichever your codebase already leans on.
3. Margin auto — for a block with a known width

The oldest trick: a block-level element with an explicit width and margin: 0 auto centers itself horizontally within its parent. This only centers on the inline axis, and only works because the element has a defined width — auto margins need free space to distribute.

CSS
.centered-block {
  width: 600px;
  max-width: 100%;
  margin: 0 auto; /* top/bottom: 0, left/right: auto */
}
No width, no centering
margin: 0 auto does nothing on an element without an explicit or constrained width — a default block element already stretches to fill its parent, so there is no free space left for the margins to consume.
4. Absolute positioning + transform

Useful when the child must be taken out of normal flow entirely — for example, centering a modal over the whole viewport regardless of surrounding content.

CSS
.parent {
  position: relative; /* establishes the positioning context */
}

.centered-child {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
Why the transform, not just top/left: 50%
top: 50%; left: 50% positions the element's top-left corner at the center point, which is not the same as centering the element itself. translate(-50%, -50%) then shifts the element back by half of its own width and height, landing its center exactly on that point — and it works without knowing the element's size in advance.
5. Text-align + line-height — inline content only

For a single line of text (or an inline/inline-block element like an icon) inside a fixed-height container, you rarely need flexbox at all.

CSS
.badge {
  height: 40px;
  line-height: 40px; /* matches the height -> vertical centering */
  text-align: center;  /* horizontal centering */
  white-space: nowrap;
}
Breaks with multi-line text
Matching line-height to the container height only centers a single line. As soon as the text wraps to two lines, the second line pushes past the box and the vertical centering breaks. Use flexbox or grid for anything that might wrap.
Quick decision table

Situation

Best technique

Center anything, both axes, size unknown

flexbox (justify-content + align-items) or grid (place-items)

Center a block with a known/max width, horizontal only

margin: 0 auto

Center an overlay/modal over its container regardless of flow

position: absolute + transform: translate(-50%, -50%)

Center a single line of text or an icon in a fixed-height box

line-height + text-align: center

Center a grid item among many, without affecting siblings

place-self: center on that one item

Common pitfalls
  • Forgetting the parent needs a defined height for vertical centering to have any space to work with (min-height: 100vh, or a fixed height, or align-items: stretch from an ancestor)

  • Using margin: 0 auto on an element without a set width — nothing happens

  • Centering text with line-height and then adding more content that wraps to two lines

  • Forgetting position: relative on the parent when using absolute-positioned centering — the child centers relative to the nearest positioned ancestor, which may be the viewport instead

  • Reaching for absolute positioning to center normal in-flow content — it removes the element from flow and can overlap siblings unexpectedly

CSS
/* The safe, all-purpose default for a new component */
.center-anything {
  display: flex;
  justify-content: center;
  align-items: center;
}

/* If you need it to also handle overflow gracefully (long content) */
.center-anything-safe {
  display: flex;
  justify-content: center;
  align-items: safe center; /* falls back to start alignment on overflow */
}
align-items: safe center
Plain center alignment can push overflowing content off-screen with no way to scroll to it. Adding the safe keyword tells the browser to fall back to start-alignment when the content would overflow, keeping it reachable.
Grid with two children — auto-margin variant

Grid can center using the same margin-auto trick as flexbox, useful when you already have a grid container for other layout reasons and do not want place-items to also center unrelated siblings.

CSS
.grid-parent {
  display: grid;
}

.centered-item {
  margin: auto; /* centers this one item both ways within its grid cell */
}
The ancient technique: table-cell centering

Before flexbox existed, vertical centering commonly relied on display: table-cell, which has always supported vertical-align properly (unlike normal block elements). It still works today and occasionally shows up in older codebases.

CSS
.table-cell-parent {
  display: table;
  width: 100%;
  height: 300px;
}

.table-cell-child {
  display: table-cell;
  vertical-align: middle;
  text-align: center;
}
Why this fell out of favor
Table-cell centering works, but it inherits table layout quirks (sizing behaves like an actual HTML table) that make it awkward to combine with other layout needs. Flexbox and grid solve the same problem with fewer surprising side effects, which is why this approach is now mostly historical.
Flexbox vs Grid centering — the real difference

Scenario

Better fit

Centering exactly one child, nothing else in the container

Either works identically — pick whichever the codebase already uses

Centering one item while other siblings need their own independent positioning/sizing

Grid, using place-self on just that item without affecting the container-wide alignment

A row of several items that should distribute and stay centered as a group

Flexbox, since justify-content: center naturally centers the whole group of items together

Centering and RTL layouts

Every technique on this page is direction-agnostic except the absolute positioning one, which is worth double-checking in a right-to-left context.

CSS
.centered-child {
  position: absolute;
  inset-inline-start: 50%;      /* logical equivalent of left/right */
  top: 50%;
  transform: translate(-50%, -50%);
}
inset-inline-start over left
left: 50% always means the physical left edge, regardless of text direction. inset-inline-start automatically flips to the correct physical side in an RTL context, which matters if the component needs to support both directions.
Next
See centering used inside a real component pattern in The Cover Layout.