Skip to content

CSS Centering

When to use

Use this skill when centering elements — horizontally, vertically, or both. The right centering method depends on the layout context, not habit. One-element demos make every method look identical; they diverge the moment a container has multiple children, an element overflows, or the layout changes under stress.

The top: 50%; left: 50%; transform: translate(-50%, -50%) pattern still works but is legacy — anchor-based and inset-based approaches are simpler and more maintainable today.

Decision guide

ScenarioMethod
Block container, single or multiple itemsalign-content: center on the container
Grid containerplace-content: center
Flex container, responsive wrapflex-wrap: wrap + place-content: center
Absolute or fixed positioned elementinset: 0 + place-self: center
Anchor-positioned elementposition-area or anchor-center
Text within its line boxtext-box: cap alphabetic
Overflow must stay visibleplace-content: safe center

Block container (single or multiple items)

align-content: center works on block-level containers in modern browsers — no display change required. justify-items: center centers inline content horizontally but is Chrome-only as of 2026.

css
.container {
  display: block;
  align-content: center;    /* centers children vertically in block containers */
  justify-items: center;    /* Chrome-only: centers inline children horizontally */
}

Use align-content: center when you want the simplest vertical centering without changing the display mode. Skip justify-items on block containers until cross-browser support improves.

Grid

place-content is the shorthand for both align-content and justify-content. On a grid container with a single item, it centers the item both axes in one declaration.

css
.container {
  display: grid;
  place-content: center;
}

Flexbox (responsive wrap)

Adding flex-wrap: wrap before place-content: center makes centering work correctly when multiple children wrap. Without flex-wrap, align-content has no effect on single-line flex containers.

css
.container {
  display: flex;
  flex-wrap: wrap;
  place-content: center;
}

Prefer this over the bare display: flex; justify-content: center; align-items: center pattern — it handles multiple wrapped children correctly and is more concise.

Absolute / fixed positioning

Instead of the legacy top: 50%; left: 50%; transform: translate(-50%, -50%) hack, use inset: 0 with place-self: center. This is simpler, readable, and handles any size.

css
/* Legacy pattern — avoid */
.overlay {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

/* Modern replacement */
.overlay {
  position: absolute;
  inset: 0;
  place-self: center;
}

inset: 0 expands the element's position constraints to all four edges of its containing block, and place-self: center centers it within that space.

Anchor positioning

CSS anchor positioning offers two centering mechanisms depending on what you're centering relative to:

Area-relative centeringposition-area places the anchored element in a region relative to the anchor. Use center for centering on both axes:

css
.anchored {
  position: absolute;
  position-anchor: --my-anchor;
  position-area: center;
}

Anchor-relative centeringanchor-center on justify-self or align-self centers the element on the corresponding axis of the anchor element itself, not a grid area:

css
.tooltip {
  position: absolute;
  position-anchor: --trigger;
  bottom: anchor(top);
  justify-self: anchor-center;   /* horizontally centered on the anchor */
}

Note the difference: position-area: center centers within the layout area; anchor-center aligns the element's center to the anchor's center on one axis.

Text centering with text-box

The default line box includes font metric whitespace (ascenders, descenders, leading) above capital letters and below baselines, making text appear vertically off-center in containers. text-box removes this whitespace.

css
/* For uppercase or mixed-case text */
.heading {
  text-box: cap alphabetic;
}

/* For lowercase text without ascenders or descenders */
.label {
  text-box: ex alphabetic;
}
  • cap trims the space above the cap height (top of uppercase letters).
  • ex trims to the x-height (top of lowercase letters without ascenders).
  • alphabetic trims below the baseline (removes descender whitespace).

Use text-box when centering text in buttons, badges, or icon + text pairs where pixel-precise vertical alignment matters. Without it, the text will visually appear above center even when mathematically centered.

Safe vs. unsafe alignment

By default, centering is unsafe — the center wins even if content overflows and is clipped. Add safe to preserve content visibility when overflow occurs.

css
/* Content can clip on overflow — default behavior */
.container {
  display: grid;
  place-content: center;
}

/* Content stays visible — overflows start edge instead of clipping */
.container {
  display: grid;
  place-content: safe center;
}

The unsafe keyword is occasionally needed explicitly in anchor positioning when a containing block (e.g., a sticky header) would otherwise constrain an anchored element like a tooltip:

css
.tooltip {
  justify-self: unsafe anchor-center;
}

Use safe center as the default for scrollable or dynamic-content containers. Use unsafe only when the design requires the anchor-relative position to win over viewport or containing-block constraints.

Trade-offs

  • Block align-content vs. flex/grid: Block align-content is the lowest-friction change but has the least cross-browser history — test early. Flex and grid centering are well-supported everywhere.
  • justify-items on block containers: Chrome-only as of 2026. Don't rely on it in production until Firefox and Safari ship it.
  • text-box support: Broadly available in modern browsers as of 2025, but verify for your target audience before using in production.
  • Anchor positioning: Good support in Chrome/Edge; Firefox and Safari added support in 2024–2025. Check browser support for position-area and anchor-center specifically, as these shipped later than the core spec.
  • inset: 0 + place-self vs. translate hack: The modern approach requires the element to be position: absolute/fixed inside a positioned parent, same as the legacy approach. The advantage is readability and avoiding a transform that can interfere with other transforms.

Source

Temani Afif, The State of CSS Centering in 2026, CSS-Tricks, May 2026.