If you know the difference between content width and box width then basically, box width must be wider than content width if you want margin: 0 auto; to center your content.
If you don’t like CSS and you have problems with it, you probably also had a problem with centering things on your beautiful web page.
You most definitely headed to Google and searched for a method that will center your content. Then you came across a fantastic solution margin: 0 auto; which, according to some online CSS tutorials ALWAYS centers. Well, it does not and this article will tell you why.
Before we start talking about margins, it’s crucial to understand what exactly box model is... If you ever used the element selector in Chrome’s dev tools, you probably already know that when you hover on an element with that tool you will see margins, borders, paddings and content - all colored differently. All you need to remember is that: content is the blue element and box is all of those elements (margins + borders + paddings + content).
Margin and his friends
But what exactly is margin for? Many people think it is just this tiny space to add between elements in order to make them a bit further away from one another... Yes, you can use them to give your elements a little bit of space, but margins are also commonly used to center or position elements in HTML and you might not even know when that happens.
By setting for example: margin-left: 50px you’ll force your browser to set that empty space to the left from your element, on the other hand, using margin: 0 auto; will tell the browser something like this: “I don’t want any empty space from the top and the bottom, but I want to have as much empty space from my left and right as possible”, it won’t force that in any way.
To get the full understanding of margins you need to think about those content and box things that I’ve mentioned earlier. On the screen above all these elements are the same except they have different margin:... set, in order from top:
- margin: 0;
- margin-left: 50px;
- margin-right: 100px;
- margin-left: 80px;
- margin-left: 80px; margin-right: 100px;
All these boxes (margin + content) have the same width, so… by setting the margin property we haven’t changed the whole box width, instead we decreased the content (blue rectangle) width.
So what will happen if we set margin: 0 auto; to the element above?
Nothing! Why? Because as I said: margin: 0 50px; will force element to have this margin, but margin: 0 auto; won’t. In this situation, it will add as much margin as possible… but how to add margin if our content is 100% wide? Content width == Box width, there’s no space for margin without forcing it. So what should we do? In this case, it’ll be enough to specify the content width so it’ll be smaller than the box, how to do it? Just set: width or max-width property in this scenario. So I’ll just add width: 500px to that element and...
Boom! Our element is centered, so in result it has: width: 500px; margin: 0 auto; NOTE: Please don’t mistake the element with the text inside of it, we just have centered the element to its container not the text to the element.
Right now I hope you know the difference between box and content, so now we can resolve our riddle: When does margin: 0 auto; center?
First things first, each of the elements above are blocks and have set margin: 0 auto, but it does not work since blocks have width equal to 100% by default (the first example). The block covers the whole page and therefore cannot be centered. If we set, for example, the width 300px and margin: 0 auto it will magically center - like in the second example. You can do the same thing be using max-width property (the third example).
As far as inlines go, they just don’t work, because in CSS they are treated more like text. The whole box of these elements tries to fit the content, so as a result, our box is getting the same size as content inside of it which means our content is not centered because again the content width has the same size as the box, but here if we set the width property it won’t change, because the box will also get smaller to fit its content, in the end, it’s useless to use margin:0 auto; on inline/inline-block elements.
Pssst: In this scenario, you can just simply add a text-align: center; to their container to center them, so it’s even simpler.
Flex / table
With flex, it is a similar scenario to blocks. It is by default 100% wide so it won't be centered with margin: 0 auto; only (the first example). You have to set width or max-width to a flex element then it will work (the second example).
In the case of tables, they are kind of weird to me, but thankfully they are not commonly used. It is enough to set margin: 0 auto; without anything else to center a table element (the third example). Why is it so simple? Tables have box width equal to 100% (like blocks), but the content width is as small as possible (like inlines). Yes, if we set the width or min-width property to anything but 100% it will still be centered.
Advanced positioning (absolute/fixed) changes the game here if you set the position: absolute/fixed; for example, for block elements and even if you set the width property, it still won’t be centered. For position: absolute/fixed it is important to set the left and the right property for those elements so the whole box can be wider than the content. By default, using position: absolute/fixed; will make the box fit its content (the first example), so again we cannot center because the box is equal to the content.
It doesn’t matter what is your element display property, it can be block, inline, inline-block, flex or table all of them will behave the same.
There’s no sense in using margin: 0 auto; for centering horizontally absolute/fixed elements, a better option is: left: 50%; top: 50%; transform: translateX(-50%);
When does margin: 0 auto; center:
- For position: static/relative/sticky; element must be a block, flex or a table.
- For position: absolute/fixed; display can be set to anything, but left and right properties should be set.
- Logically, a content width cannot equal 100%