There is no single way to center

For years, centering a div was the running joke of CSS. The truth now is almost the opposite problem: there are too many ways, and they are not interchangeable. A method that perfectly centers a single box can be the wrong call for a row of items, and vice versa.

So this is not a list of tricks to copy. It is a guide to the question you should actually ask: what am I centering, on which axis, and inside what kind of container? Answer that and the right method picks itself.

Grid place-items: the one-line default

If you want a single element centered both ways inside a parent, grid is the shortest correct answer.

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

Two lines, no magic numbers, works on a child of any size. place-items is shorthand for align-items and justify-items, so it handles the block and inline axes at once. This is the method to reach for first when you have one thing to center.

The full walkthrough is in centering without the transform hack.

Flexbox: when you are centering a group

Grid centering shines for one item. The moment you are centering a row or column of several items, flexbox is usually the better mental model, because it is built around distributing items along an axis.

.parent {
  display: flex;
  justify-content: center;
  align-items: center;
}

Add flex-wrap: wrap and a gap and you have a centered cluster that reflows cleanly on small screens. See centering with flexbox for the details.

Auto margins: the quiet classic

You do not always need a new formatting context. To center a block horizontally, an auto margin still does the job, and it has worked in every browser for two decades.

.box {
  inline-size: 40rem;
  margin-inline: auto;
}

It needs a defined size to push against, and it only handles the inline axis on its own, but for the everyday case of centering a content column it is the least code with the fewest surprises. More in centering with auto margins.

Absolute centering without the transform hack

The old way to center an absolutely positioned element was the 50% offset plus a negative translate(-50%, -50%) to pull it back by half its own size. It worked, but it was fiddly and it fought subpixel rounding.

The modern replacement pins all four edges and lets the margin or alignment do the centering, no transform needed.

.overlay {
  position: absolute;
  inset: 0;
  margin: auto;
  inline-size: max-content;
  block-size: max-content;
}

This is the cleanest way to drop a fixed-size panel in the dead center of a positioned ancestor. The snippet centering without the transform hack covers the variations.

Centering text on its real letterforms

Centering a box is one problem. Centering text inside a fixed shape, like a button, is a different one, because fonts ship invisible space above the cap line and below the baseline. That half-leading is why button text always looks a pixel high.

text-box-trim removes it, so the text aligns to its actual letterforms instead of the font's metric box.

.btn {
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
}

Pair it with place-items: center on the button and the label lands dead center on the first try. Full detail in centering button text without line-height tweaks and vertical text centering without padding hacks.

The newer methods: block-level alignment

The most recent shift is that the box-alignment properties are starting to work in plain block layout, with no display: grid or display: flex needed. The promise is centering a child without ever changing the container's formatting context.

.parent {
  align-content: center;
}

[VERIFY SUPPORT before publishing: confirm align-content in block layout against caniuse (css-align-content-block) and MDN BCD. Get exact Chrome/Safari/Firefox/Edge versions and Baseline status. Per CLAUDE.md, do not state any version or baseline label until verified. Likely still Limited or Newly available, so frame as emerging, not safe-to-ship-everywhere.]

Until support is confirmed wide, treat this as a progressive enhancement over the grid method, not a replacement.

The newer methods: anchor-center

Anchor positioning introduced a dedicated value for centering an element on the thing it is anchored to: anchor-center, used with justify-self, align-self, or place-self.

.tooltip {
  position-anchor: --trigger;
  justify-self: anchor-center;
}

[VERIFY SUPPORT before publishing: anchor-center value confirmed to exist on justify-self/place-self via MDN. Still need exact browser versions and Baseline status from caniuse + MDN BCD. Anchor positioning overall is not yet Baseline widely available, so frame accordingly and do not invent version numbers.]

This is the right tool when the centered element is a popover, tooltip, or menu tied to a trigger, rather than a child centered in a container.

How to choose

The decision, in one place. One element, both axes, inside a container: display: grid; place-items: center. A group of items along an axis: flexbox with justify-content and align-items. A content column, horizontal only: margin-inline: auto. An absolutely positioned panel: inset: 0; margin: auto with a set size. Text inside a shape: text-box-trim. An element tied to a trigger: anchor-center once support is there.

The CSS-Tricks state-of-centering piece put it best: the goal is not to memorize every method, it is to understand how alignment works so you can pick the one that fits. Centering stopped being a trick. It became a choice.