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 :)
- Using position absolute hack
- 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
.