Learn CSS · Lesson 8 of 11 · 7 min
Centering, decided
Centering has a reputation for being hard, and the reputation is ten years out of date. It was never one problem. It is seven different situations that happen to share a word, and each one now has a short, boring answer. The skill is not memorising tricks. It is noticing which situation you are in.
Three questions
Answer these about the thing in front of you. The right card lights up, and the rest of the lesson is those seven cards.
The seven answers
A line of text inside its box
text-align: center; Goes on: the box that holds the text.
Text is inline content, and inline content is aligned by the box around it. This one has not changed in twenty years and does not need to.
A box, left to right, in the page
Widely availablemax-width: 60ch;
margin-inline: auto; Goes on: the box itself.
A block is as wide as its parent, so there is nothing to centre until you give it a width. Then auto margins split the leftover space evenly.
What it replaced: margin: 0 auto, which also reset the top and bottom margins whether you meant to or not.
One thing, both directions, in its parent
Widely availabledisplay: grid;
place-items: center; Goes on: the parent.
Two lines, no knowledge of the child’s size needed, and it keeps working when the content changes. If you remember one answer from this lesson, this is the one.
What it replaced: position: absolute with top: 50%, left: 50% and a transform of -50% each way.
Several things in a row, centred as a group
Widely availabledisplay: flex;
justify-content: center;
align-items: center;
gap: 12px; Goes on: the parent.
Flexbox centres along its main axis with justify-content and across it with align-items. gap spaces the items without a margin on each one.
What it replaced: inline-block items with text-align: center on the parent, and a whitespace bug between them.
Ordinary block content, top to bottom, in a tall box
Newly availablealign-content: center; Goes on: the tall box.
Newer than the rest: align-content now works on a plain block, with no flex or grid at all. One line, and the box keeps behaving like a normal block inside.
What it replaced: display: table-cell with vertical-align: middle, or a ghost pseudo-element.
A layer over the whole page
position: fixed;
inset: 0;
width: fit-content;
height: fit-content;
margin: auto; Goes on: the layer.
inset: 0 stretches the positioning box to all four edges, and auto margins centre a sized element inside it. No transform, so the text stays sharp and nothing sits on a half pixel.
What it replaced: top: 50%, left: 50% and translate(-50%, -50%), which blurs text on some screens.
A modal or a popover
Widely available<dialog> … </dialog>
/* dialog.showModal() */ Goes on: nothing: the browser centres it.
A modal dialog is centred by the browser, sits in the top layer above everything, traps focus and closes on Escape. The best centring code is the code you do not write.
What it replaced: a fixed div, a backdrop div, a z-index, a focus trap library and a keydown listener.
Try it
The second and fourth cards both space things with modern properties.
Logical properties are why the card says
margin-inline and not margin-left: the same rule is correct in a
right-to-left language. For a dialog that needs placing next to a button instead of mid-screen, see
anchor positioning and popover.
When NOT to centre
Centred body text is harder to read than left-aligned text, because the eye loses its place when every line starts somewhere different. Centre headlines, short labels and single calls to action. Leave paragraphs alone. And do not centre a whole page by centring everything inside it: centre the one column (card two), and let its contents line up along its edge.
The transform trick still has one honest use: centring something on a point you do not control, such as a marker on a map. For laying out an interface, it is no longer the first tool or the second.
Practice
- Open the Bento Grid Builder, put one tile in a cell, and centre its label with card three. Then add a second label and watch card three stop being the right card.
- Take any page you have built and find a
translate(-50%, -50%). Work out which of the seven situations it is, and replace it. - Give a box a fixed height and some paragraphs, add
align-content: center, and check the badge on card five before you ship it.
Check yourself
A sign-in card has to sit in the middle of an otherwise empty screen. Which card?
Card three. One thing, both directions, in its parent. Make the page a grid that is at least
the height of the screen (min-height: 100svh) and use place-items: center.
A footer has five links that should sit together in the middle of the row. Which card?
Card four. Several things in a row, centred as a group: flex, justify-content: center,
and gap for the spacing between them.
An article’s text column should sit in the middle of a wide screen. Which card, and what is the step people forget?
Card two, and the forgotten step is the width. A block fills its parent, so auto margins have no
leftover space to divide until you set a max-width.
The mental model to keep
Centering is a property of the relationship between a thing and its container, which is why most of these declarations go on the parent and not on the thing being centred. When centring fights you, the usual cause is that you are styling the wrong one of the two.
Last reviewed 2026-09-18. Browser status on this page is read from the web-features dataset when the site is built, not typed.