Center anything, both axes
Centers any child both horizontally and vertically in two lines of CSS, using grid's place-items shorthand instead of flexbox's two rules.
Last updated
.center {
display: grid;
place-items: center;
}
/* centers every direct child, both axes, in one declaration */How it works
place-items is shorthand for align-items and justify-items together — on a grid container, setting it to center centers a child along both the block (vertical) and inline (horizontal) axes in that single line, where the flexbox equivalent needs both align-items: center and justify-content: center to do the same job.
This works with zero knowledge of the child's size or the container's size, which is what makes it the reliable default reached for over margin tricks or absolute positioning plus transforms — it centers correctly whether the child is 20px or 200px, and reflows correctly if either size changes later.
Edge cases to know
- →The flexbox equivalent (display: flex; align-items: center; justify-content: center;) does the identical job and is worth reaching for instead if the container already needs to be a flex context for other reasons (gap-based row/column layout, flex-wrap, etc.) — there's no need to switch a working flex container to grid just for centering.
- →margin: auto on a block-level child centres it horizontally ONLY — vertical auto margins compute to 0 in normal block flow. Auto margins centre on both axes only inside a flex or grid parent, so they are not a way to avoid setting display.
- →place-items centers every direct child independently, not the container's content as a block — with multiple children, each one centers in its own grid cell rather than the group centering together as a unit.
Part by part
- display: grid
- Establishes a grid container. A single-cell grid is the simplest possible layout and the one alignment behaves most predictably in.
- place-items: center
- Shorthand for align-items and justify-items together, centring every child on both axes at once.
Common mistakes
.center { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }The classic approach, and it removes the element from flow, requires a positioned ancestor, and can land on a half-pixel that blurs text. Two declarations do the same job without any of that.
.center { display: grid; place-items: center; }.center { display: grid; place-content: center; }place-content centres the grid tracks within the container rather than the items within their cells. With a single auto-sized track the difference shows the moment the container is larger than the content.
Expecting it to centre within the viewportIt centres children within this element, which is only as tall as its content unless told otherwise. Add a height — 100dvh for a full screen — or nothing appears to move vertically.
Questions
Does it work with several children?
They all stack into the same cell and overlap, since a single-cell grid places every child there. For several centred items side by side, use flex with justify-content and align-items instead.
What is the flexbox equivalent?
display: flex with justify-content: center and align-items: center, or place-items on a flex container in modern browsers. Grid needs fewer declarations, which is the only real difference for this case.
Why 100dvh rather than 100vh?
Because mobile browsers change viewport height as the address bar hides, and vh uses the largest value — so a 100vh element is taller than the visible area. dvh tracks the dynamic height and avoids the jump.
Does it centre text as well?
It centres the text block as a box, not the lines within it. Add text-align: center if the lines themselves should be centred — the two are independent and frequently both wanted.