Fixing CSS margin auto not working issues

CSS margin auto not centering your content? Check out these possible solutions to resolve your issue!

Jan 8, 2023 | Read time 12 minutes

🔔 Table of contents

Introduction

A common CSS trick to center a element within its parent is using the margin:auto property. For example, in the below, we can center the element of a class of .child with 500px within its parent element using the margin: 0 auto property:

.parent {
  text-align: center;
}

.child {
  width: 500px;
  margin: 0 auto;
}

To issues with margin: auto not working in CSS, you need to make sure that the element you are trying to center has a width and placed in a valid parent element with defined width. If the element still isn’t being centered as expected, you should check for any conflicting styles that might be overriding the margin: auto rule. You can also try using the text-align: center property on the parent element to center the child element. We can use different methods for centering the element, such as using absolute positioning or using flex.

How does margin:auto work?

We can center elements by using the margin auto property.

According to the specs, https://developer.mozilla.org/en-US/docs/Web/CSS/margin, margin is a shorthand CSS property that is supposed to replace the four:

  • margin-left,
  • margin-right,
  • margin-top,
  • margin-bottom

So we can set margin without explitly writing out the above four properties like so:

/* Apply to all four sides - 1rem each margin */
margin: 1rem;

/* Apply 1rem to the top/bottom and 2rem to left/right */
margin: 1rem 2rem;

/* Apply 1rem to the top, 2rem to the left/right and 3rem to the bottom margins */
margin: 1rem 2rem 3rem;

/* Top and bottom to have zero margin and left/right to be auto - 
which centers the containing element */

margin: 0 auto;

The auto keyword just tells the browser to set the suitable margin to use for that element. Commonly used to center a element within its containing parent element!

1. Check for display:block

The most common reason why using margin:auto is not working for your designs is that the element’s display property is inline. This applies to elements like <span>, <strong>, <em>, etc.

With inline elements, they do not inherently have a width and therefore using margin auto will not work. This is setting margin:auto we are telling the browser to center a element based on the width.

To fix this, we just need to explicitly set the display CSS property to display:block. Any value that is not inline should work - eg display:inline-block, display:table, etc

Consider the following HTML structure:

<div class="container">
   <span>Center me</span>
</div>
.container span{
  margin:0 auto;
}

Now the above will not work, because <span> by default is a inline display (display:inline) and therefore cannot set the width. To fix this, we need to change it over to display:block and set the width.

(Note: we can also use min-width here)

.container span{
  display:block; /* ✔️Add display block */
  width: 200px; /* ✔️ Use explicit width */
  margin:0 auto;
}

Tip: Consider using display:inline-block

Using display:inline-block is considered the sweetspot between trying to keep a element inline, but still able to control the width of the element!

2. Check for float CSS property

One thing to check is that we are not using the float property somewhere in our CSS stying. Adding float to a element removes it from the normal flow of the document. It allows you to place elements left or right side of a containing element and lets the text wrap around it.

Since margin:auto tells the browser to adjust margins based on the width, having something float will not work since the element will be outside of the control flow!

Consider the following HTML structure, we have a parent element and accidentally placed a float:right on the child element:

<div class="container">
   <span>Center me</span>
</div>
.container span{
  display:block; 
  width: 200px; 
  margin:0 auto;
  float:right; /* ✔️ Will override the margin auto property and places this element on the ride side */
}

In the above, even when we have margin:0 auto, adding a float:right will move the element outside of the normal document flow (ignoring margin auto calculations) and places it on the very right side of the parent container!

3. Check the element for a width value

To make sure that margin:auto is centering your elements correctly, we need to check that the element contains a explicit width property.

Consider the below HTML structure. We have a two divs - a parent div with .container class and we want to center the child div with CSS class .content.

<div class="container">
   <div class="content">Center me</div>
</div>
.content{
  margin:0 auto; /* ❌Will not work */
}

The above will not work because margin:auto relies on the width of the element. With <DIV> elements, they have default of 100% width. So the parent element will be 100% of the page, and the child element (.content) will also have 100% width of the parent.

To fix this we need to add a width value for the DIV with the .content CSS class:

.content{
  margin:0 auto; 
  width: 200px; /* ✔️ Use explicit width */

}

4. Check for conflicting styles

A common problem that you can encounter is using margin:auto on one styling can be overwritten by another style.

In this case, we need to check the specifity of the element you are trying to style.

For example, you could have a styling that is more specific or using the !important keyword.

Lets consider the following example. We want to make the child of a .container DIV font to have color of red:

<div class="container">
    <div class="content" style="margin:1rem">XXX</div>

</div>

Our CSS can have multiple

.container .content { /*❌ Will not work! */
  margin:auto;
}

The above will not work, since the DIV with .content class got a inline style. Inline stylings has higher specitivity than CSS class selectors. So in this case, the margin:auto will not be applied, but the margin:1rem in the inline style - eg <div class="content" style="margin:1rem">XXX</div>

What is CSS specificity?

Specificity is how browsers decide on which style to apply to which element. Based on the CSS selector is an order in which styles will be applied!

Generally, selectors with IDs will override classes. In turn, CSS selectors with classes will override pseudo-classes such as :last-child!

5. Check for browser support

Margin auto is widely available across modern browsers.

The margin auto property was initially used to center elements within a HTML container before flex or grid layouts came along. So if you are trying to support old browsers (such as IE10 or below) you might need to consider reverting back to margin:auto from your flex layouts!

One thing of note is that margin auto is not available in quirks mode for browsers like IE10 or below! Quirks mode is just a mode for browser to support legacy browsers such as Netscape and IE5 before the advent of W3C standards.

Typically we can trigger quirks mode by not including the <!DOCTYPE html> tag. Any HTML file that has the <!DOCTYPE html> tag will tell browsers that your page uses full standards mode.

Using margin:auto to center vertically

A common question or confusion is trying to use margin:auto to center a element vertically. Based on the previous CSS2 specification (https://www.w3.org/TR/CSS2/visudet.html#Computing_heights_and_margins) we cannot center it vertically since margin-top:auto and margin-bottom:auto the used value would compute to zero.

Now looking deeper into the algorithm that calculates the height there are two ways you can get around this :)

  1. Using position absolute hack
  2. Using flexbox

Consider the following HTML structure for the below hacks:

<div class="container">
   <div class="content">Center me</div>
</div>

Now when we try to center the DIV with .content class vertically, it does not seem to work (even when we follow the above steps)

.container{
  width:400px;
  height:400px;
}
.content{
  width:100px;
  height:100px;
  border:1px solid black;
  margin:auto; /*❌ Not centering vertically - only horizontal */
}

We can fix this using the two hacks below:

1. Vertically center using margin auto position absolute hack

We can vertically center the .content DIV with the position absolute hack. First we need to add a CSS position property for the .container DIV - eg position:relative.

Then for our .content DIV, we can add the following hack of setting the position to absolute and top/bottom/left/right to zero:

position:absolute; top:0; bottom:0; left:0; right:0;

So our final CSS will look like:

.container{
  width:400px;
  height:400px;
  position:relative; /* ✔️ Add position relative */
}
.content{
  width:100px;
  height:100px;
  position:absolute;   /* ✔️ Postion needs to be absolute (or fixed) */
  top:0;               /* ✔️ Make top 0 */
  bottom:0;            /* ✔️ Make bottom 0 */
  left:0;              /* ✔️ Make left 0 */
  right:0;             /* ✔️ Make right 0 */
  margin:auto;
}

2. Vertically center using margin auto and flexbox

Margins work particularly well with flexbox - especially dealing with margin:auto. Auto margins on flex items have an effect very similar to auto margins in block flow - It is described in the specs here:

https://www.w3.org/TR/css-flexbox-1/#auto-margins

So we can expect similar behaviour as using display:block - since “any positive free space is distributed to auto margins in that dimension”

.container{
  width:400px;
  height:400px;
  display:flex;
}

.content{
  width:100px;
  height:100px;
  border:1px solid black;
  margin:auto;
}

Summary

In this post we looked at using margin:auto to center elements in CSS. There are a few gotchas when using this technique. To center a element with margin:auto, we need to specify explicitly the width of the element. Additionally, the element should not be a inline element (eg <span>, <strong>, etc). Inline elements have default display:inline - for margin:auto to work it needs to have display:block or display:inline-block.

We also looked at a few ways to make margin:auto work to center a element vertically. We can do this using the position absolute hack or making the parent container flex - using display:flex.

👋 About the Author

G'day! I am Huy a software engineer based in Australia. I have been creating design-centered software for the last 10 years both professionally and as a passion.

My aim to share what I have learnt with you! (and to help me remember 😅)

Follow along on Twitter , GitHub and YouTube