How to Center a Div: Every Method, Side by Side

Centring a div both ways takes two lines on the parent: display: grid; place-items: center; or display: flex with justify-content: center and align-items: center. For horizontal only, give the div a width and margin-inline: auto. The parent needs a height taller than the child for vertical centring to show.

The short version
NeedCSS on the parentTailwind
Both waysdisplay: grid; place-items: centergrid place-items-center
Both waysdisplay: flex; justify-content: center; align-items: centerflex items-center justify-center
Horizontal block(on the child) margin-inline: auto + a widthmx-auto w-…
Over an imageposition: relative, child inset: 0 + margin: autorelative / absolute inset-0 m-auto

Updated

Pick a method and an axis and the demo box moves, the CSS for the parent and child is written out, and a note says where that method breaks. Seven techniques are covered, including the old ones you will still meet in existing code, followed by a decision table for picking one.

All seven methods with their CSS

Flexbox

Flexbox: parent and child CSS
AxisParentChildTailwind
horizontaldisplay: flex; justify-content: center;(nothing)flex justify-center
verticaldisplay: flex; align-items: center; height: 220px;(nothing)flex items-center h-[220px]
bothdisplay: flex; justify-content: center; align-items: center; height: 220px;(nothing)flex items-center justify-center h-[220px]

Vertical centring needs the parent to be taller than the child. With flex-direction: column the two properties swap axes.

Grid place-items

Grid place-items: parent and child CSS
AxisParentChildTailwind
horizontaldisplay: grid; justify-items: center;(nothing)grid justify-items-center
verticaldisplay: grid; align-items: center; height: 220px;(nothing)grid items-center h-[220px]
bothdisplay: grid; place-items: center; height: 220px;(nothing)grid place-items-center h-[220px]

Several children stack in rows, each centred in its own row, so they spread out vertically instead of sitting together. Wrap them in one element.

margin: auto

margin: auto: parent and child CSS
AxisParentChildTailwind
horizontal(nothing)width: 140px; margin-inline: auto;w-[140px] mx-auto
verticalNot possible--
bothNot possible--

In normal block flow it only centres horizontally, and only when the child has a width smaller than the parent. Inside a flex or grid parent, margin: auto centres both ways.

Absolute + transform

Absolute + transform: parent and child CSS
AxisParentChildTailwind
horizontalposition: relative;position: absolute; left: 50%; transform: translateX(-50%);relative / absolute left-1/2 -translate-x-1/2
verticalposition: relative; height: 220px;position: absolute; top: 50%; transform: translateY(-50%);relative h-[220px] / absolute top-1/2 -translate-y-1/2
bothposition: relative; height: 220px;position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);relative h-[220px] / absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2

The child leaves the flow, so the parent no longer grows around it. Half-pixel offsets can blur text, and the transform makes the child a containing block and stacking context.

Absolute inset + margin auto

Absolute inset + margin auto: parent and child CSS
AxisParentChildTailwind
horizontalposition: relative;position: absolute; inset-inline: 0; width: 140px; margin-inline: auto;relative / absolute inset-x-0 w-[140px] mx-auto
verticalposition: relative; height: 220px;position: absolute; inset-block: 0; height: 60px; margin-block: auto;relative h-[220px] / absolute inset-y-0 h-[60px] my-auto
bothposition: relative; height: 220px;position: absolute; inset: 0; width: 140px; height: 60px; margin: auto;relative h-[220px] / absolute inset-0 m-auto w-[140px] h-[60px]

The child needs an explicit size on the centred axis. Without it, inset: 0 simply stretches the child to fill the parent. fit-content widths also work in current browsers.

text-align: center

text-align: center: parent and child CSS
AxisParentChildTailwind
horizontaltext-align: center;display: inline-block;text-center / inline-block
verticalNot possible--
bothNot possible--

Only moves inline content: text, images, inline-block boxes. A normal block div ignores it, and the text inside the child inherits the centring too.

line-height

line-height: parent and child CSS
AxisParentChildTailwind
horizontalNot possible--
verticalheight: 60px; line-height: 60px;display: inline-block; line-height: normal; vertical-align: middle;h-[60px] leading-[60px] / inline-block leading-normal align-middle
bothheight: 60px; line-height: 60px; text-align: center;display: inline-block; line-height: normal; vertical-align: middle;h-[60px] leading-[60px] text-center / inline-block leading-normal align-middle

Breaks as soon as the text wraps onto a second line, and the height has to be hard-coded twice. Fine for a one-line badge or button, nothing else.

Decision table

Which method for which job
MethodHorizontalVerticalBothWatch out for
FlexboxYesYesYesVertical centring needs the parent to be taller than the child. With flex-direction: column the two properties swap axes.
Grid place-itemsYesYesYesSeveral children stack in rows, each centred in its own row, so they spread out vertically instead of sitting together. Wrap them in one element.
margin: autoYesNoNoIn normal block flow it only centres horizontally, and only when the child has a width smaller than the parent. Inside a flex or grid parent, margin: auto centres both ways.
Absolute + transformYesYesYesThe child leaves the flow, so the parent no longer grows around it. Half-pixel offsets can blur text, and the transform makes the child a containing block and stacking context.
Absolute inset + margin autoYesYesYesThe child needs an explicit size on the centred axis. Without it, inset: 0 simply stretches the child to fill the parent. fit-content widths also work in current browsers.
text-align: centerYesNoNoOnly moves inline content: text, images, inline-block boxes. A normal block div ignores it, and the text inside the child inherits the centring too.
line-heightNoYesYesBreaks as soon as the text wraps onto a second line, and the height has to be hard-coded twice. Fine for a one-line badge or button, nothing else.

Copy-ready recipes

A card in the middle of the screen

In a real page use min-height: 100dvh on the wrapper. The frame here uses a fixed height so it fits.

<div style="min-height: 200px; display: grid; place-items: center; background: #f1f5f9">
  <div style="padding: 16px 20px; background: #fff; border-radius: 12px; box-shadow: 0 4px 16px #0002">
    Sign in to continue
  </div>
</div>

Play button over a thumbnail

inset: 0 with margin: auto centres a fixed-size child without transform, so edges stay crisp.

<div style="position: relative; height: 170px; max-width: 300px; background: linear-gradient(135deg,#1e3a8a,#4F98FB); border-radius: 12px">
  <button style="position: absolute; inset: 0; margin: auto; width: 56px; height: 56px; border-radius: 50%; border: 0; font-size: 20px">&#9654;</button>
</div>

One item centred, others at the edges

Auto margins on a flex child take all spare space, so the logo sits in the middle of the bar while menu and cart stay at the sides.

<nav style="display: flex; align-items: center; gap: 8px; padding: 10px; background: #0f172a; color: #fff">
  <span>Menu</span>
  <strong style="margin-inline: auto">Bakehouse</strong>
  <span>Cart</span>
</nav>

Two directions, two different problems

Horizontal centring is easy in block layout because width is known: the parent's width is fixed by its container, so auto margins can split the leftover space. Height is the opposite, it is decided by the content, which is why vertical centring needed tricks for years.

Flexbox and grid changed that by letting the parent distribute free space on both axes. Once the parent has a known height, alignment properties do the rest, and the child stays part of the normal flow.

When the old methods still make sense

Absolute positioning is right when the centred thing should float over other content, such as a play button over a video thumbnail or a spinner over a card. The inset plus margin auto version avoids the blurry half-pixel edges a translate can produce.

text-align is still the quickest way to centre an icon or inline button inside a line of text. line-height centring belongs only in one-line badges you control fully.

How it works

  1. Choose horizontal, vertical or both.
  2. Click through the methods. Methods that cannot do the chosen axis say so instead of pretending.
  3. Read the failure note for the method, then copy the CSS or Tailwind classes.
  4. Check the decision table below when you are not sure which to use.

Tips

Frequently asked questions

Why will my div not centre vertically?

Usually because the parent has no extra height. A block is only as tall as its content, so there is no space to centre within. Give the parent a height, min-height (for example 100dvh for a full screen) or let it stretch inside a taller flex or grid layout.

What is the shortest way to centre a div?

display: grid; place-items: center; on the parent. It centres the child both ways, works for any child size and needs no width or height on the child.

How do I centre a div on the whole page?

Make body or a wrapper at least the viewport height: min-height: 100dvh; display: grid; place-items: center;. For a modal that floats above the page, use position: fixed; inset: 0; margin: auto; with a set width and height, or the native dialog element, which centres itself.

Does margin: 0 auto still work?

Yes, for horizontal centring of a block that has a width narrower than its parent. margin-inline: auto is the modern logical form and leaves the top and bottom margins untouched.

How do I centre a div in Tailwind?

Put flex items-center justify-center, or grid place-items-center, on the parent and give it a height such as h-screen or min-h-dvh. For a horizontally centred block, add mx-auto and a width or max-width to the child.

Related: Flexbox and grid cheat sheet, CSS position guide, CSS box model, CSS text styling, CSS transforms.

Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.

More in Guides

We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.

Product

Who It's For

Features

Resources

Company

View Sitemap