
How to Center a Div in CSS: Every Method Explained
"How do I center a div?" has been a running joke among web developers for as long as CSS has existed. The joke landed because, for years, the answer really was complicated: tables, negative margins, magic numbers, and a lot of trial and error. Today the story is very different. Modern CSS gives you several clean, predictable ways to center anything, horizontally, vertically, or both.
The catch is that there isn't one universal answer. The right method depends on what you are centering (text, a block, an image, an overlay), what it is centered inside (a card, the viewport, a positioned parent), and whether the element has a known size. This guide walks through every method worth knowing, explains how each one actually works, and tells you when to reach for it.
First, Understand What "Center" Means
Before picking a technique, answer two questions:
- Which axis? Horizontal centering (left to right) and vertical centering (top to bottom) are solved by different mechanisms in older layout modes. In Flexbox and Grid, both axes are handled together.
- Centered relative to what? An element is always centered inside something: its parent, its containing block, or the viewport. If the parent has no height, there is no vertical space to center within, and no technique will appear to work.
That second point causes more "centering is broken" bugs than anything else. If you are trying to vertically center content inside a div whose height is determined by its content, the content already fills it. Give the parent a height (or min-height) first.
Here is the HTML we will use for most examples:
<div class="parent">
<div class="child">I am centered</div>
</div>
And a bit of shared styling so you can see what's happening:
.parent {
min-height: 320px;
background: #f1f5f9;
border: 2px dashed #94a3b8;
}
.child {
padding: 1.5rem 2rem;
background: #38bdf8;
color: #0f172a;
border-radius: 8px;
}
Method 1: CSS Grid with place-items
If you only remember one technique, make it this one:
.parent {
display: grid;
place-items: center;
}
That's it. Two lines, both axes, no knowledge of the child's size required.
place-items is shorthand for align-items and justify-items. In a grid container, align-items: center centers each item vertically inside its grid area, and justify-items: center centers it horizontally. Because we haven't defined any columns or rows, the grid creates a single implicit cell that fills the container, and the child sits in the middle of it.
When to use it
- Centering a single element inside a card, hero section, or modal backdrop.
- Centering an icon inside a circular button.
- Any time you want the shortest possible correct answer.
Things to watch
If you put several children inside a place-items: center grid, they stack vertically in separate rows, each centered. That's often what you want, but if you expected them side by side, use Flexbox instead. Also note that the child shrinks to fit its content, because justify-items: center stops it from stretching to the full width.
Method 2: Flexbox with justify-content and align-items
Flexbox was the first layout mode that made centering easy, and it remains the go-to when you have a row (or column) of items:
.parent {
display: flex;
justify-content: center;
align-items: center;
}
In a flex container, justify-content controls distribution along the main axis (horizontal by default) and align-items controls alignment on the cross axis (vertical by default). Setting both to center puts the child in the exact middle.
If you switch to flex-direction: column, the axes swap: justify-content now controls vertical placement and align-items controls horizontal placement. The combination of both set to center still centers in both directions, which is why this snippet is so dependable.
Centering a group of items
Flexbox shines when you center multiple elements as a group:
<div class="toolbar">
<button>Cut</button>
<button>Copy</button>
<button>Paste</button>
</div>
.toolbar {
display: flex;
justify-content: center;
align-items: center;
gap: 0.75rem;
min-height: 80px;
}
The three buttons stay on one line, spaced by gap, and the whole group is centered.
Using place-content in Flexbox
You can also write place-content: center on a flex container. It sets align-content and justify-content. The spec originally said align-content has no effect on single-line flex containers, and browsers have only recently started changing that behavior, so this shorthand doesn't vertically center consistently everywhere. Stick with justify-content plus align-items for Flexbox.
Method 3: margin: auto Inside Flex or Grid
Auto margins have a special superpower inside flex and grid containers: they absorb all available free space in their direction. Put auto on all four sides and the element is pushed equally from every edge.
.parent {
display: flex; /* or grid */
}
.child {
margin: auto;
}
This is handy when you want to center one specific child without changing how its siblings are aligned. For example, a "loading" message inside an otherwise normal flex layout can center itself without touching the parent's alignment properties.
A related trick: margin-left: auto on the last item in a navbar pushes it to the far right, while the rest stay on the left. It's the same mechanism, just applied to one side.
Method 4: margin: 0 auto for Horizontal Centering of Blocks
This is the classic, and it still has a place. A block-level element with a set width and auto left/right margins is centered horizontally inside its parent:
.container {
max-width: 960px;
margin-inline: auto;
}
margin-inline: auto is the logical property equivalent of margin-left: auto; margin-right: auto;. It also works correctly in right-to-left languages.
The key requirement is a width that's less than the parent's width. A block element without a width stretches to fill its parent, so there's no free space for the auto margins to share. That's why this pattern almost always appears with max-width or width.
What margin: 0 auto cannot do is center vertically in normal flow. Auto margins on the top and bottom of a regular block compute to zero. That's the reason people struggled for so long, and the reason Methods 1 through 3 exist.
Using fit-content for shrink-wrapped blocks
If you want a block to be only as wide as its content and still center it, combine width: fit-content with auto margins:
.badge {
width: fit-content;
margin-inline: auto;
}
Method 5: text-align: center for Inline Content
For text, inline elements, and inline-block elements, text-align: center on the parent is still the correct tool:
.card-footer {
text-align: center;
}
It centers inline content within a line box, not the block itself. That means it works for text, links, <img> elements (which are inline by default), and anything with display: inline-block. It won't move a block-level div unless you change that div's display.
<div class="card-footer">
<a class="button" href="/signup">Create account</a>
</div>
.button {
display: inline-block;
padding: 0.75rem 1.5rem;
background: #818cf8;
color: #fff;
}
Because text-align is inherited, be aware that everything inside the container, including paragraphs, will also center. Reset it on descendants if needed.
Method 6: Absolute Positioning with inset and margin: auto
Sometimes you need to take an element out of normal flow, for example a badge over an image, a loading spinner over a card, or a dialog over the page. Absolute positioning handles this.
The modern, size-agnostic version:
.parent {
position: relative;
}
.child {
position: absolute;
inset: 0;
margin: auto;
width: fit-content;
height: fit-content;
}
inset: 0 sets top, right, bottom, and left to zero, stretching the element's containing box across the parent. With margin: auto and an explicit (or content-based) width and height, the browser distributes the leftover space equally on all sides. The element is centered on both axes.
Without the width and height, the element would simply stretch to fill the parent, so they matter here. Support for fit-content in width and height is good across modern browsers.
Method 7: Absolute Positioning with transform
This is the technique that dominated the 2010s, and you'll still see it everywhere:
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
Here's the logic. top: 50% and left: 50% place the child's top-left corner at the center of the parent. Percentages in translate(), however, refer to the element's own size, so translate(-50%, -50%) shifts it back by half its own width and height. The result is a perfectly centered element, regardless of its dimensions.
You can also use the individual translate property, which is supported in all current major browsers:
.child {
position: absolute;
top: 50%;
left: 50%;
translate: -50% -50%;
}
Using translate separately means you can animate transform (for example, a scale on hover) without accidentally overwriting the centering offset.
Downsides of the transform method
- Transforms can cause slightly blurry text on some displays when the element lands on a half-pixel.
- If you already use
transformfor animation, the centering and the animation will fight each other unless you use the separatetranslateproperty. - The element is removed from flow, so the parent won't grow to fit it.
Method 8: Centering Relative to the Viewport
For modals, cookie banners, and full-screen overlays, you usually want to center relative to the browser window rather than a parent. Use position: fixed:
.modal {
position: fixed;
inset: 0;
margin: auto;
width: min(90vw, 480px);
height: fit-content;
}
Or, if you have a full-screen backdrop wrapper, make the backdrop a grid:
<div class="backdrop">
<div class="dialog" role="dialog" aria-modal="true">...</div>
</div>
.backdrop {
position: fixed;
inset: 0;
display: grid;
place-items: center;
background: rgb(15 23 42 / 0.6);
}
If you use the native <dialog> element with showModal(), browsers already center it in the viewport by default using the inset: 0; margin: auto approach. You usually only need to set a width.
Method 9: Centering a Full-Page Layout
Centering a login form in the middle of the screen is a common case. The trick is to give the body enough height:
body {
margin: 0;
min-height: 100svh;
display: grid;
place-items: center;
}
The svh unit (small viewport height) accounts for mobile browser toolbars, avoiding the classic problem where 100vh is taller than the visible area on phones. It's supported in all current major browsers. For older browsers, add a 100vh line before it as a fallback:
body {
min-height: 100vh;
min-height: 100svh;
}
Method 10: Vertical Centering of Single-Line Text with line-height
An older trick, still occasionally useful for small UI elements like badges or pills with fixed heights:
.pill {
height: 32px;
line-height: 32px;
padding-inline: 12px;
}
Setting line-height equal to height places the single line of text in the vertical middle. It breaks the moment the text wraps to a second line, so only use it where wrapping is impossible. For anything else, Flexbox is safer:
.pill {
display: inline-flex;
align-items: center;
height: 32px;
padding-inline: 12px;
}
Method 11: align-content on Block Containers
A newer addition to CSS lets you vertically center content in a plain block container, without switching to Flexbox or Grid:
.parent {
align-content: center;
min-height: 320px;
}
align-content was historically limited to flex and grid containers, but the spec now allows it on regular block containers, and recent versions of Chromium, Firefox, and Safari support it. The advantage is that the children keep normal block layout, so margins collapse and widths behave as usual. Check support for your audience before relying on it; if older browsers matter, keep a Grid-based fallback.
.parent {
/* Older browsers: switch to grid so align-content applies */
display: grid;
align-content: center;
min-height: 320px;
}
A feature query can't tell whether a browser supports align-content on block containers specifically (it already knows the property from Flexbox and Grid), so treat the block version as an enhancement and use Grid wherever older browsers matter.
Common Pitfalls
The parent has no height. Vertical centering needs vertical space. If the container is exactly as tall as its content, the content is already "centered". Add min-height.
Centering the wrong element. Alignment properties like justify-content and place-items belong on the parent. margin: auto belongs on the child. Mixing them up is the most common mistake.
Forgetting that inline elements ignore width. A span won't respect width or margin: auto. Change it to display: block or inline-block first.
Overflow on small screens. A centered element that's taller than the viewport can get its top clipped off-screen when using Flexbox centering. Use the safe keyword to fall back to start alignment when content overflows:
.parent {
display: flex;
align-items: safe center;
justify-content: safe center;
}
The safe keyword is supported in current versions of the major engines, but check caniuse if you need older browsers. Alternatively, margin: auto on the child in a flex container behaves "safely" by default: auto margins never become negative.
Text-align leaking. text-align: center is inherited. If you use it to center a button, every paragraph below it will also center.
Which Method Should You Use?
Here's a quick decision guide:
| Situation | Best method |
|---|---|
| One element, both axes, inside a container | display: grid; place-items: center |
| A row of items centered as a group | Flexbox with justify-content + align-items |
| A page wrapper with a max width | max-width + margin-inline: auto |
| Text, links, inline images | text-align: center |
| Overlay on top of other content | position: absolute; inset: 0; margin: auto |
| Modal or banner in the viewport | position: fixed + inset: 0 + margin: auto, or a grid backdrop |
| Legacy codebases | top: 50%; left: 50%; translate: -50% -50% |
Conclusion
Centering a div stopped being hard the day Flexbox and Grid landed in every browser. For most layouts, display: grid; place-items: center is the shortest, most readable answer, and Flexbox covers groups of items. margin-inline: auto remains the right tool for page containers, text-align for inline content, and absolute or fixed positioning for overlays and modals.
The real skill is knowing why each method works: which element the property belongs on, which axis it controls, and what space it's centering within. Once that clicks, you'll pick the right technique instinctively and stop reaching for magic numbers. The joke can finally retire.


