How to center an element in CSS?
Center an element horizontally and vertically in CSS with grid, flexbox or absolute positioning, and fix the most common reason vertical centering fails.
To center an element both horizontally and vertically, make its parent a grid container and add place-items: center. Two lines on the parent, nothing on the child.
.hero {
display: grid;
place-items: center;
min-height: 400px;
}<section class="hero">
<div class="hero-content">Centered</div>
</section>The min-height isn't part of the centering, but without it the parent is exactly as tall as its content and there's nothing to center vertically. More on that below.
Flexbox
Flexbox does the same with justify-content for the main axis and align-items for the cross axis:
.hero {
display: flex;
justify-content: center;
align-items: center;
min-height: 400px;
}The difference shows up with more than one child. Grid puts each child in its own row, so the children stack vertically, each centered in its row. Flex puts them next to each other and centers the whole row. I use grid for a single element, like a modal or an empty state, and flex when I center a group of items such as icons or buttons.
Both versions shrink the child to its content width instead of stretching it. If the child should keep a certain width, give it one, for example width: min(100%, 32rem).
Absolute positioning
When the element has to sit on top of other content, like a play icon over a video thumbnail, position it absolutely inside a position: relative parent. There are two ways to center it.
With inset: 0 and margin: auto, the browser splits the free space evenly. This only works when the element has a size, otherwise it stretches to fill the parent:
.thumbnail {
position: relative;
}
.play-icon {
position: absolute;
inset: 0;
width: 48px;
height: 48px;
margin: auto;
}If you don't know the size in advance, width: fit-content and height: fit-content work too.
The other way moves the element's top-left corner to the middle, then shifts the element back by half of its own size:
.play-icon {
position: absolute;
top: 50%;
left: 50%;
translate: -50% -50%;
}In older code you'll see transform: translate(-50%, -50%), which does the same thing. The standalone translate property is better, because a transform: scale(1.1) on hover no longer overwrites it and sends the element jumping out of the center.
Horizontal only
A block element with a width is centered with auto margins on the left and right:
.container {
max-width: 64rem;
margin-inline: auto;
}margin-inline: auto is the logical version of margin-left: auto; margin-right: auto. Without a width or max-width the block already fills the whole row, so there's no free space to split.
Text, links, inline images and inline-block elements aren't centered with margins. Use text-align: center on their parent:
.card-footer {
text-align: center;
}Why vertical centering doesn't work
The most common cause is a parent without a height. A block is as tall as its content by default, so the child is already "centered" in a box that fits it exactly, and nothing moves.
Give the parent a height or a min-height. For a full-screen section, use min-height: 100dvh. How to make an element 100% of the screen height explains why 100vh misbehaves on phones.
The second cause is putting the centering properties on the child. place-items, justify-content and align-items go on the parent.
align-content on a normal block
Newer: align-content: center now also works on regular block containers, without display: flex or display: grid. It landed in all major browsers in 2024, so check Can I Use if you support older ones.
.banner {
align-content: center;
min-height: 200px;
}It centers the content vertically and leaves the rest of the layout as normal block flow. I like it for boxes where switching to flex would change how the children lay out. The parent still needs a height.