Centring a div is the oldest joke in CSS: it sounds like one line, and for years it took a hack. Modern CSS has two reliable answers, flexbox and grid, and once you know which box the rules go on, it stops being a guessing game.
Why it used to be hard
Horizontal centring has worked for a long time. A block element with a set width centres itself with margin: 0 auto, because the browser splits the spare width equally between the left and right margins.
Vertical centring is where it fell apart. In normal flow, a block is as tall as its content, and auto margins on the top and bottom resolve to zero, so there is no spare height to share out. Developers worked around it with absolute positioning and negative margins, display: table-cell, or a line-height matched to the box. Negative margins need the element's exact size, and the line-height trick only works for a single line of text.
Centre it with flexbox
Flexbox lays out a container's children along a line, and it can share out spare space in both directions:
.parent {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}justify-content works along the main axis, which is horizontal in a default row. align-items works along the cross axis, which is vertical. Switch to flex-direction: column and the two swap jobs, so justify-content now centres vertically.
Centre it with grid
Grid does the same job in fewer lines:
.parent {
display: grid;
place-items: center;
min-height: 100vh;
}place-items is shorthand for align-items and justify-items, so one declaration centres the child both ways. It suits a single child in a box. When several items sit in a row, flexbox gives you more control over the spacing between them.
Common mistakes
- Putting the rules on the child does nothing. Both methods go on the container, and the div being centred needs no rules of its own.
- A parent with no height is only as tall as the child, so the child is centred in a box that fits it exactly and nothing seems to move. Give the parent a
heightormin-height. text-align: centercentres inline content, such as text and images, inside a block. It does not move the block itself.margin: 0 autodoes nothing to a block that already fills its container, so give it a width first.
Key takeaways
- Put the centring rules on the parent, not the div you want centred.
- Flexbox:
justify-contentandalign-items, both set tocenter. - Grid:
display: gridwithplace-items: center. - The parent needs a height before vertical centring can show.
margin: 0 autocentres horizontally only, and needs a width.