How to Center with CSS Flexbox — Every Case Covered

Quick answer

💡Add display: flex to the parent container, then set justify-content: center to center horizontally and align-items: center to center vertically. Use both properties together for the classic 3-line center. The child element needs no special properties for basic centering.

Error symptoms

  • Element is flush to the top-left corner despite centering rules
  • justify-content: center works but align-items: center has no effect
  • Element centers horizontally but not vertically
  • Text centers but the element itself does not
  • Centering works on desktop but breaks on mobile
  • margin: auto works horizontally but not vertically

Common causes

  • display: flex is missing from the parent — it must be on the container, not the child
  • No defined height on the container — align-items needs vertical space to center within
  • flex-direction: column changes the axis — justify-content and align-items swap roles
  • Using place-items: center on a flex container — that shorthand is for Grid, not Flexbox
  • Applying justify-content or align-items to the child instead of the parent
  • A wrapper element has height: 0 or overflow: hidden blocking the expected visual result

When it happens

  • Building hero sections, login pages, or loading screens
  • Centering a modal, card, or badge within its container
  • Vertically aligning icons with text inside a button or nav item
  • Creating full-viewport centered layouts with 100vh
  • Converting table-cell vertical-align tricks to modern CSS

Examples and fixes

The most common pattern — centering a child on both horizontal and vertical axes.

Center both axes in a container

❌ Wrong

<div class="card-wrapper">
  <div class="card">Sign In</div>
</div>

/* CSS */
.card-wrapper {
  height: 400px;
}
.card {
  text-align: center;
  vertical-align: middle;
}

✅ Fixed

<div class="card-wrapper">
  <div class="card">Sign In</div>
</div>

/* CSS */
.card-wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 400px;
}

text-align only affects inline content; vertical-align only works on table cells. The fix puts display: flex on the parent. justify-content: center centers along the main axis (horizontal when flex-direction is row, the default). align-items: center centers along the cross axis (vertical). The child card needs no CSS changes at all for this basic case.

Center a login form in the exact middle of the browser window.

Full-viewport centered layout

❌ Wrong

<body>
  <div class="login-form">Login</div>
</body>

/* CSS */
body {
  text-align: center;
}
.login-form {
  margin-top: 200px;
}

✅ Fixed

<body>
  <div class="login-form">Login</div>
</body>

/* CSS */
body {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  margin: 0;
}

A fixed margin-top breaks at different screen heights. Using min-height: 100vh on the body flex container ensures the container spans the full viewport. justify-content and align-items then place the login-form precisely in the center regardless of screen size. margin: 0 on body removes the default browser margin that would otherwise cause a small overflow on the vertical axis.

Use margin: auto on a single flex child to push it to center without affecting siblings.

Center one item while others stay left-aligned

❌ Wrong

<nav class="toolbar">
  <span>Logo</span>
  <span class="centered-badge">Beta</span>
  <span>Menu</span>
</nav>

/* CSS */
.toolbar {
  display: flex;
}
.centered-badge {
  text-align: center;
}

✅ Fixed

<nav class="toolbar">
  <span>Logo</span>
  <span class="spacer"></span>
  <span class="centered-badge">Beta</span>
  <span class="spacer"></span>
  <span>Menu</span>
</nav>

/* CSS */
.toolbar {
  display: flex;
  align-items: center;
}
.spacer {
  flex: 1;
}

text-align: center on a flex item only affects its text content, not its position in the flex row. Inserting flex: 1 spacer elements before and after the badge pushes it to the true center while leaving Logo and Menu in their natural positions. align-items: center on the container vertically centers all three items regardless of their individual heights.

Why flexbox centering fails

The most frequent cause of broken flexbox centering is placing the display: flex rule on the wrong element. Flexbox is a parent-child relationship: the flex container property must live on the parent, and it controls the layout of that element's direct children only. If you add justify-content: center to a child element, nothing will happen because that child is not a flex container with items to arrange.

Another common failure is forgetting that align-items requires vertical space to work in. When a flex container has no defined height — or inherits height: auto from its parent — there is no cross-axis space to distribute, so align-items: center has no visible effect. The fix is to give the container an explicit height, min-height, or ensure it stretches to fill its parent.

The flex-direction property also changes which axis each property controls. The default is flex-direction: row, meaning the main axis runs left to right. justify-content controls horizontal placement; align-items controls vertical placement. When you switch to flex-direction: column, the main axis becomes vertical — so justify-content now controls vertical placement and align-items controls horizontal. This trips up many developers when building stacked layouts.

Finally, place-items: center is not a Flexbox shorthand. It is valid in CSS Grid and sets both align-items and justify-items on a grid container. Using it on a flex container will not produce the expected centering because justify-items has no effect on flex containers. Always use the explicit justify-content and align-items properties when working with Flexbox, not place-items.

Diagnosing centering with DevTools

Open Chrome or Firefox DevTools and inspect the element you expect to be centered. Select the parent container — not the child — and look at the Styles panel. You should see display: flex listed in the computed rules. Chrome 88 and Firefox 71+ both show a purple or colored flex badge directly on the element in the Elements panel; clicking it opens the Flexbox inspector overlay that draws the main axis, cross axis, and free space as visual guides over the page.

In the Layout tab of Chrome DevTools, a Flexbox section lists every flex container on the page. Check the flex container's computed height. If it shows 0px or auto with no resolved value, the container has no height — add a fixed height, min-height, or make the container stretch via height: 100% through its parent chain.

Look at the flex items themselves. A common mistake is seeing justify-self: center on a flex item and assuming it will center the item — that property does nothing in a flex context. Only justify-content on the parent moves items along the main axis. Cross out suspect rules temporarily in the Styles panel by unchecking the checkbox to the left of each declaration, and watch whether the layout changes.

For mobile debugging, toggle device simulation in DevTools and check at 375px and 390px widths. A container that uses vh units may shrink unpredictably on mobile browsers that show or hide their address bar. Use svh (small viewport height) in modern browsers for consistent full-screen centering on mobile.

Applying the correct centering pattern

The standard 3-line flexbox center is: display: flex; justify-content: center; align-items: center on the parent container. That covers the vast majority of cases. The child does not need any additional properties to be positioned in the center of the parent.

For centering a single flex item when other items are present, use margin: auto on that one child. A flex item with margin-left: auto will be pushed as far right as possible; margin: auto expands in all directions and pushes the item to the center of the remaining free space. This technique is common for centering an icon in a toolbar while keeping other items at their natural positions.

For vertical centering when flex-direction is column, swap your mental model: justify-content now controls vertical alignment and align-items controls horizontal. So display: flex; flex-direction: column; justify-content: center; align-items: center centers both axes with a column layout. You still need a defined height on the container.

For the align-self property on a child — use it to override align-items for one specific item. If the parent has align-items: flex-start but you want one card centered, add align-self: center to that card. This does not affect any siblings.

For Grid as an alternative: display: grid; place-items: center is genuinely simpler for centering when you only have one child element. It sets both align-items and justify-items to center in one declaration. Prefer Flexbox when you need to arrange multiple children in a row or column; prefer Grid when you need precise two-dimensional placement or a single centered element.

Edge cases and browser gotchas

Safari 14 and earlier have known issues with min-height on flex containers inside elements with display: flex and flex-direction: column. If you set min-height: 100vh on a flex column container in Safari, it may not pass height down to nested flex children correctly. The workaround is to set height: 100vh instead of min-height, or add flex: 1 on intermediate wrapper elements to explicitly distribute the available height.

On mobile, the 100vh value includes the browser chrome (address bar, navigation bar) in some browsers. This means a centered element positioned at 50vh may not visually appear in the center of the screen. Modern browsers support svh (smallest viewport height), lvh (largest), and dvh (dynamic) units. Use height: 100dvh for layouts that should track the visible viewport as the browser chrome shows and hides.

Images inside flex containers can overflow because images default to display: inline with their natural dimensions. Adding max-width: 100% to images inside a flex container prevents them from overflowing their flex track. For consistent behavior, set width: 100% and height: auto on images, or use object-fit: cover with explicit dimensions.

When a flex container wraps with flex-wrap: wrap, align-items only aligns items within each row, not across all rows. Use align-content to control spacing between multiple rows. align-content: center requires the container to be taller than the total height of all rows — exactly the same height requirement as align-items.

Internet Explorer 11 supports Flexbox but with several bugs and requires the -ms- vendor prefix for some properties. If you must support IE 11, test justify-content and align-items manually and consider a PostCSS autoprefixer. Most modern teams drop IE 11 support — global usage fell below 0.3% in 2023.

Mistakes that break flexbox centering

The single most repeated mistake is applying display: flex and the alignment properties to the element you want to center instead of to its parent. A flex container arranges its children. If .card has display: flex, it is arranging its own children — not positioning itself within its wrapper.

A close second is relying on text-align: center as a replacement for flex centering. text-align works on inline content within a block container. It does not move block-level children or flex items. A centered paragraph of text inside an off-center div still looks correct for the text but the div itself is not centered.

Using vertical-align: middle is also wrong outside a table-cell context. It is a property for inline and table elements. In a flex container it has no effect at all — not even an override. Developers from older CSS backgrounds often reach for it instinctively.

Setting justify-content: center without a defined height and then expecting vertical centering is another very common trap. When the container's height is determined by its content, there is no free space on the cross axis. Adding height: 300px or min-height: 200px immediately makes align-items: center work.

Finally, mixing up justify-content and align-items when using flex-direction: column. In a column flex container, justify-content moves items up and down; align-items moves them left and right. The labels are accurate descriptions of which axis the property controls relative to the flex direction, but muscle memory from row layouts gets in the way.

A related mistake is applying flex-direction: column to the wrong element in a nested layout. When a parent wrapper has flex-direction: column but the developer intended to center within a child container, centering properties on the parent govern the child's vertical stacking, not the internal centering of the child's own children. Always confirm which element is the actual flex container before adding centering properties, especially in deeply nested components.

Best practices for flexbox centering

Define centering intent in the parent only. Keep the child element's CSS focused on its own appearance — color, typography, border — and let the parent control positioning. This separation makes it easy to reuse the child in different containers with different alignment requirements.

Use a utility class for common centering patterns. A class like .flex-center with display: flex; justify-content: center; align-items: center; can be applied to any parent that needs its content centered, similar to how Tailwind's flex items-center justify-center works. Consistent naming prevents the same property from being rediscovered in every component.

Prefer min-height over height for flex containers that center content. A parent with height: 400px will clip taller children; min-height: 400px allows the container to grow if its content exceeds the minimum. This is especially important for centering within page sections that may contain dynamic content.

Always test centering at the smallest breakpoint you support. Content that centers correctly at 1280px may overflow or collapse at 375px if the flex container has no flex-wrap and the child has a fixed width. Add flex-wrap: wrap or use max-width constraints on children to make centering robust at all screen sizes.

Document the centering pattern in a comment when the CSS is non-obvious — for example, when you are using negative margin plus transform, or the spacer flex: 1 technique for centering one item in a multi-item row. Inline comments prevent the next developer from removing a style they do not understand and breaking the layout silently and unexpectedly.

Quick fix checklist

  • Confirm display: flex is on the parent container, not the child
  • Check the parent has an explicit height or min-height for vertical centering
  • Use justify-content: center for horizontal alignment
  • Use align-items: center for vertical alignment
  • If using flex-direction: column, remember the axes are swapped
  • Do not use place-items on a flex container — it only works in Grid
  • Test at 375px mobile width and confirm no overflow occurs
  • Avoid vertical-align and text-align as substitutes for flexbox alignment

Related guides

Frequently asked questions

Why does align-items: center not work on my flex container?

The container almost certainly has no explicit height. align-items distributes free space on the cross axis — if the container's height is determined by its content, there is no free space to distribute. Add a height, min-height, or make the container fill its parent with height: 100% or flex: 1.

What is the difference between justify-content and align-items in flexbox?

justify-content aligns items along the main axis, which is horizontal by default when flex-direction is row. align-items aligns items along the cross axis, which is vertical by default. When you switch to flex-direction: column these two roles swap — justify-content controls vertical alignment and align-items controls horizontal alignment.

Can I use place-items: center to center in flexbox?

No. place-items is a shorthand for align-items and justify-items. The justify-items property has no effect in Flexbox — it only works in Grid. Use justify-content: center and align-items: center separately on a flex container to achieve centering on both axes.

How do I center a flex item vertically without centering all items?

Use align-self: center on the specific child you want to center. align-self overrides the parent's align-items value for that one element. All other sibling flex items continue to follow the parent's align-items setting. This is useful for centering icons or badges within a row of mixed-height elements.

Why does flexbox centering work on desktop but break on mobile?

The most common cause is the 100vh issue on mobile browsers. The address bar takes up viewport height, so 100vh is taller than the visible area. The layout shifts when the browser chrome hides on scroll. Switch to height: 100dvh for dynamic viewport height that adjusts automatically. Also check for fixed-width children that force the container wider than the screen.

Is grid centering better than flexbox centering?

For a single centered element, display: grid; place-items: center is more concise — one property instead of two. For centering one or more items in a row or column, Flexbox is more natural because you can also control wrapping, gap, and ordering. Both approaches work well; choose based on whether you need one-dimensional or two-dimensional layout control.

How do I center a child element horizontally only?

Set display: flex; justify-content: center on the parent and leave align-items at its default value of stretch. The child will be horizontally centered and will fill the full height of the container. Alternatively, use margin: 0 auto on a block-level child with a defined width for simple horizontal centering without Flexbox.

Why does margin: auto work for horizontal centering but not vertical?

In normal flow, vertical margins never collapse to center an element because there is no available vertical space defined by the block formatting context. Inside a flex container, margin: auto absorbs all free space in the specified direction — including vertically. So margin: auto on a flex child will center it both horizontally and vertically within the available space.

All tools run in your browser. Your data never leaves your device. Last updated: 2026-05-06.