
To centre a div inside its container, give the container display: flex; justify-content: center; align-items: center;. justify-content centres horizontally, align-items vertically. If the vertical centring is not visible, the container has no height: add min-height: 100vh for the whole page, or an explicit height.
Centring a div in CSS used to call for tricks. Not any more: three lines of Flexbox centre any element inside its container, horizontally and vertically. This article starts with that short answer, then goes through each situation, from centring an image to centring a button, with the Grid alternative and the mistakes that make people think “it doesn’t work”.
The short answer
.conteneur {
display: flex;
justify-content: center; /* horizontal */
align-items: center; /* vertical */
}<div class="conteneur">
<div class="boite">Je suis centrée</div>
</div>Both properties go on the parent, never on the element to be centred. And vertical centring is only visible if the parent is taller than its content: that is the first thing to check when nothing moves.
Centring horizontally
With Flexbox
justify-content distributes the children along the main axis, horizontal by default. center gathers them in the middle.
.conteneur {
display: flex;
justify-content: center;
gap: 1rem; /* space between several centred children */
}With several children, they stay side by side, centred as a group. That was the case of the two paragraphs, or the two images, in this article’s original example.
With margin auto
Without Flexbox, a block of known width is centred with automatic margins:
.boite {
width: 320px; /* or max-width: essential */
margin: 0 auto;
}Without a width or a max-width, the box takes up the full available width and the automatic margins are zero. This is the method to remember for centring a column of content in a page.
With text-align
text-align: center centres the inline content of a block: text, a link, an inline image. It does not centre the block itself inside its parent.
.titre {
text-align: center; /* centres the text inside .titre */
}Centring vertically
align-items handles the cross axis, vertical by default. The container needs a height for the centring to be visible.
.conteneur {
display: flex;
align-items: center;
height: 300px;
}To centre only one child vertically and leave the others at the top, align-self goes on that child:
.conteneur .dernier {
align-self: center;
}Another way of writing it, often shorter: margin: auto on the child of a flex container centres it in both directions, by absorbing all the free space.
.conteneur { display: flex; height: 300px; }
.boite { margin: auto; }Centring on the whole page
A login screen, an error message, a waiting page: the element has to sit in the centre of the window. The container takes the full visible height with min-height: 100vh.
body {
margin: 0;
}
.page {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh; /* 100% of the window height */
}min-height rather than height: if the content overflows the window on a small screen, the container grows instead of cutting it off. On mobile, 100dvh (dynamic height, which takes the browser bars into account) is more accurate still, and supported by current browsers.
Centring an image
An image is an inline element: inside a block, text-align: center on the parent centres it horizontally. To centre it both ways, or inside a fixed-size frame, Flexbox is simpler.
/* Horizontal only */
figure {
text-align: center;
}
/* Horizontal and vertical, inside a square thumbnail */
.vignette {
display: flex;
justify-content: center;
align-items: center;
width: 200px;
height: 200px;
overflow: hidden;
}
.vignette img {
max-width: 100%;
max-height: 100%;
object-fit: contain;
}An image on its own in a column can also be centred as a block: display: block; margin: 0 auto; with a width or a maximum width.
Centring text and a button
Text is centred with text-align: center on its block. A button is an inline-block element: the same property on its parent centres it horizontally.
.actions {
text-align: center;
}
/* To centre several buttons with even spacing */
.actions {
display: flex;
justify-content: center;
gap: 0.75rem;
}To centre the text inside a button of fixed height, the button itself becomes a flex container: display: inline-flex; align-items: center; justify-content: center;.
The Grid alternative: a single line
CSS Grid centres a single child in one declaration:
.conteneur {
display: grid;
place-items: center; /* align-items + justify-items */
min-height: 100vh;
}Grid and Flexbox give the same result here. Grid is shorter for a single element; Flexbox remains more natural for aligning a row of elements. Choosing between the two models for a complete layout is covered in Grid or Flexbox.
position absolute + transform: the case of overlays
When the element to be centred is taken out of the flow, a tooltip or a modal window laid over the page for example, you position it at 50% and then pull it back by half its own size:
.parent {
position: relative;
}
.modale {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}The method works without knowing the element’s size, but it can make text slightly blurry when the translation lands on half a pixel. For a full-screen modal, a position: fixed; inset: 0; display: grid; place-items: center; container avoids the problem.
Why “it doesn’t work”: the five mistakes
- The parent has no height. Vertical centring is relative to the container’s height; without a height, there is nothing to centre in. Add
min-height. - The properties are on the child.
justify-contentandalign-itemsgo on the parent. On the child, onlyalign-selfandmargin: autohave any effect. margin: 0 autowithout a width. The block already takes up 100%: give it awidthor amax-width.text-align: centerto centre a div. It centres the text inside, not the box. Use Flexbox or automatic margins.height: 100%that does nothing. A percentage height only works if the parent itself has a defined height, all the way up tohtml.100vhand100dvhdo not depend on the parent.
Summary
| I want to centre… | Method |
|---|---|
| a div both ways | parent display: flex; justify-content: center; align-items: center; (+ height) |
| a div horizontally, without Flexbox | width + margin: 0 auto |
| a single child, in the fewest lines | parent display: grid; place-items: center; |
| on the whole page | the same + min-height: 100vh |
| an image | text-align: center on the parent, or Flexbox inside a frame |
| text or a button | text-align: center on the parent block |
| an overlay (modal, tooltip) | position: absolute; top/left: 50%; transform: translate(-50%, -50%) |
To go beyond centring, the complete Flexbox guide reviews every property of the container and of its children.
Common errors
align-items: center centres relative to the container's height. If that height is the content's height, nothing moves. Give the container a height (min-height: 100vh, height: 300px).justify-content and align-items go on the parent with display: flex, not on the element to be centred. Only align-self and margin: auto go on the child.width or max-width already takes up the full width: the automatic margins are zero. Set a width.

