Centre a div in CSS: horizontally, vertically or both (Flexbox, Grid)

Three lines of Flexbox to centre a div, then each case on its own: horizontal, vertical, whole page, image, text, button. With the Grid alternative, the position absolute method and the mistakes that stop centring from working.

Centre elements in CSS with Flexbox, horizontally and vertically
Quick answer

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

css
.conteneur {
  display: flex;
  justify-content: center; /* horizontal */
  align-items: center;     /* vertical */
}
html
<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.

css
.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:

css
.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.

css
.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.

css
.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:

css
.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.

css
.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.

css
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.

css
/* 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.

css
.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:

css
.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:

css
.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

  1. 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.
  2. The properties are on the child. justify-content and align-items go on the parent. On the child, only align-self and margin: auto have any effect.
  3. margin: 0 auto without a width. The block already takes up 100%: give it a width or a max-width.
  4. text-align: center to centre a div. It centres the text inside, not the box. Use Flexbox or automatic margins.
  5. height: 100% that does nothing. A percentage height only works if the parent itself has a defined height, all the way up to html. 100vh and 100dvh do 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

The container has no height 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).
Putting the properties on the child 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.
margin: 0 auto without a width A block with no width or max-width already takes up the full width: the automatic margins are zero. Set a width.
text-align: center on a div This property centres the inline content (text, inline images) inside the div, not the div itself inside its parent.

CSS

Damien Flandrin Web developer since 2010, creator of Gekkode and Email Impact. Every article is tested on a real project before publication. Contact
Newsletter

New tests, tutorials and projects, by e-mail.

Reproducible tests, versioned code, dated results. Never any spam.