Topic 6.5
Centering Anything
In one line
Pick the centering method by what you're centering: text-align: center for text and inline content, margin-inline: auto for a block with a width, place-items: center (Grid) or justify-content plus align-items (Flexbox) for both directions, and inset: 0; margin: auto or translate(-50%, -50%) for positioned boxes.
Think of it like this
Hanging a picture in the middle of a wall. You don't guess: you measure the space left over and split it equally on both sides. For a heavy frame you might use a rail that holds it in the middle automatically. CSS gives you both kinds: methods that share the leftover space equally (auto margins, Flexbox, Grid) and methods that measure from the middle (50% plus a shift back).
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Horizontal centring
- Equal space on the left and right of something (along the inline axis).
- Vertical centring
- Equal space above and below something (along the block axis).
- Leftover space
- The room in a parent that a child doesn't fill. Centring splits it equally on both sides.
- Auto margin
- A margin set to
auto, which takes a share of the leftover space. - `text-align: center`
- Centres lines of text and inline content inside their block. It doesn't move block boxes.
- `place-items: center`
- In a grid, centres every item in its area both ways. Short for
align-itemsplusjustify-items. - `justify-content` / `align-items`
- Flexbox properties that place items along the main axis and the cross axis.
- `translate(-50%, -50%)`
- A transform that shifts a box left and up by half of its own width and height.
Step by step
01Centre text
Put text-align: center on the element that contains the text. Each line is centred. If a button or image is inline or inline-block, it's centred too.
.hero {
text-align: center;
}02Centre a block horizontally
A page wrapper with a max-width and margin-inline: auto sits in the middle of wide screens and fills narrow ones. The two auto margins share the leftover width.
.container {
max-width: 960px;
margin-inline: auto; /* same as margin-left: auto; margin-right: auto */
padding-inline: 16px;
}03Centre both ways with Grid
Two lines on the parent centre its child in both directions. Give the parent a height so there's vertical space to share.
.screen {
display: grid;
place-items: center;
min-height: 100vh;
}04Centre an overlay box
For a box laid over other content, position it. With a known size use inset: 0; margin: auto; with an unknown size use the 50% and translate pair.
.modal {
position: fixed;
inset: 0;
margin: auto;
width: min(90vw, 400px);
height: fit-content;
}
.tooltip {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}05Choose the method
Follow the questions in order. The first matching answer is usually the simplest correct method.
Try it yourself
- 1
Remove the parent's height
In the first example, change
.c'sheight: 100pxtoheight: auto. Predict everytopvalue. (All 0: with no extra vertical space, there's nothing to share. Vertical centring always needs a parent taller than the child.) - 2
Centre with align-content
In the first example, add
.block { align-content: center; }. Predict theblockline. (left 70 top 30in browsers that supportalign-contenton block containers, Baseline 2024.) - 3
Make the safe keyword work
In the third example, change
justify-content: centertojustify-content: safe center. Predict the first line. (child left: 0in browsers that supportsafein flex layout.)
Code & diagrams
A 60×40 box in a 200×100 parent is centred when it is 70px from the left and 30px from the top. Five methods get both. `margin-inline: auto` in normal flow only centres horizontally: vertical auto margins count as zero in block layout.
Preview
Console
Nothing logged yet.Expected console output
flex left 70 top 30
grid left 70 top 30
flexauto left 70 top 30
abs left 70 top 30
translate left 70 top 30
block left 70 top 0`text-align: center` centres the heading, the paragraph and the inline-block button, because they are all lines of inline content inside the banner. Make the pill's text long enough to wrap and watch the `line-height` trick fall apart: each line is 40px tall.
Preview
Console
Nothing logged yet.With `justify-content: center`, the 300px child overflows **equally on both sides**, so its first 50px sit at a negative position that the scrollbar can't reach. Auto margins never go negative, so `margin: auto` falls back to the start edge and all the content can be scrolled to. The `safe` keyword (`justify-content: safe center`) asks for the same behaviour.
Preview
Console
Nothing logged yet.Expected console output
center child left: -50
auto child left: 0Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
text-align on the wrong element
To centre a <div class="card" style="width: 300px"> on the page, write .card { text-align: center; }.
Break #2
margin: auto that doesn't centre vertically
Try .box { width: 200px; height: 100px; margin: auto; } inside a tall normal <div> to centre it on the screen.
Myth vs fact
Myth
Vertical centring in CSS is hard.
Fact
It was before Flexbox. Today display: grid; place-items: center on a parent with a height does it in two lines.
Myth
margin: 0 auto centres anything.
Fact
It centres a block box that has a width smaller than its parent. It does nothing for inline elements and nothing vertically in normal flow.
Myth
translate(-50%, -50%) is the best way to centre.
Fact
It's useful when the size is unknown and the box must overlap, but it can blur text on half pixels and takes the box out of flow. Prefer Grid or Flexbox when the box doesn't need to overlap.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Centring with Flexbox or Grid can cause data loss: when the child is larger than the container, it overflows in both directions and the start side can't be scrolled to. Auto margins and the
safekeyword avoid this. This matters for modals on short phone screens. - ▸
place-items: centercentres each item in its grid area;place-content: centercentres the whole grid in the container. With one child and one auto-sized track they look the same, but they diverge once the grid has several tracks. - ▸
For full-screen centring on mobile,
min-height: 100vhcan be taller than the visible area when browser toolbars are shown;100dvh(dynamic viewport height) follows the toolbars (Phase 9 covers viewport units). - ▸
Visual centre is not always mathematical centre: text has space above capitals and below the baseline, and icons often look low. Designers nudge by a pixel;
text-box-trim(newer, not yet in every browser) trims the extra space above and below text so it can be centred precisely.
Remember this
- 1
First ask two questions. What am I centering: text and inline content, or a box? And which way: horizontally (along the inline axis), vertically (along the block axis), or both? Most "centering doesn't work" bugs come from using an inline method on a block, or a horizontal method for a vertical problem.
- 2
Text and inline content (text, links, inline-block buttons, images):
text-align: centeron the parent. It centres each line inside its line box. It doesn't move a block box, and it's inherited, so everything inside gets centred text too. For one line of text in a box of fixed height,line-heightequal to the height centres it vertically, but it breaks if the text wraps. - 3
A block box horizontally: give it a width smaller than its parent (
width,max-widthorfit-content) andmargin-inline: auto(the oldmargin: 0 auto). The browser splits the leftover space equally between the two auto margins. Without a width, a block already fills its parent, so there's no leftover space and nothing to see. In normal flow,margin-block: autodoes not centre vertically: vertical auto margins in block layout count as zero. - 4
Both directions with Grid or Flexbox (the modern default):
display: grid; place-items: center;on the parent centres the child in both directions with two declarations. With Flexbox:display: flex; justify-content: center; align-items: center;. Inside a flex or grid container,margin: autoon the child also centres it in both directions, because auto margins there absorb free space on both axes. The parent needs a height (ormin-height: 100vhfor a full screen) for vertical centring to be visible. Phases 7 and 8 explain these properties fully. - 5
Positioned boxes (overlays, modals, badges): with a known size,
position: absolute; inset: 0; margin: auto; width: ...; height: ...;centres the box in its containing block, because the auto margins share the space between the four offsets. With an unknown size,top: 50%; left: 50%; transform: translate(-50%, -50%);puts the box's top-left corner at the centre, then shifts it back by half its own size (percentages intranslaterefer to the box itself). The transform can land on half pixels and blur text slightly. - 6
Newer and older options.
align-content: centernow works on plain block containers (Baseline 2024), so a block can centre its children vertically without becoming flex or grid. For a vertical centre in old table-like layouts,display: table-cell; vertical-align: middle;still works, andvertical-align: middlelines up an inline icon with the middle of the text beside it. A centring rule of thumb: Gridplace-itemsfor one child, Flexbox for a row of items,margin-inline: autofor page-width containers,text-alignfor text, positioning only for things that should overlap.
Explain it without notes
How would you centre a block horizontally, and why does it need a width?
Show two ways to centre an element both horizontally and vertically, and say when you'd choose each.
Why doesn't margin: auto centre vertically in normal flow, but does in a flex container?
Explain how top: 50%; left: 50%; transform: translate(-50%, -50%) centres a box.
Practice
Centre a 320px-wide .login card horizontally on the page, with 40px of space above it.
Centre an <h1> both ways in a full-screen .splash section.
Put a .play button exactly in the centre of a .video box whose size you don't know, on top of the video.
Trade-offs
- ↔
Grid and Flexbox centring is short and keeps the child in flow, but the parent changes its layout mode for all its children; positioning centres without affecting siblings but takes the child out of flow.
- ↔
translate(-50%, -50%)handles unknown sizes but can render on half pixels and conflicts with other transforms on the same element;inset: 0; margin: autois crisp but needs a known orfit-contentsize.
Done when you can
I can centre text with
text-alignand a block withmargin-inline: auto.I can centre a child both ways with Grid or Flexbox.
I can centre a positioned box with
inset: 0; margin: autoand withtranslate(-50%, -50%).I know why vertical centring needs a parent with extra height.
I can choose the right centring method for a situation and explain why.