margin:auto to center a block element horizontally is a well known technique. But have you ever wondered why or how it works? To answer this, we first need to take a look at how margin:auto works. Also in the mix is what
auto can possibly do in margins, if it works for vertical centering, and a few other issues.
But first, what does
auto actually do?
The definition of
auto varies with elements, element types and context. In margins,
auto can mean one of two things: take up the available space or 0 px. These two will define different layouts for an element.
Read more: 6 CSS Tricks to Align Content Vertically
"auto" Taking Up Available Space
This is the most common use of margin
auto we come across often. By assigning
auto to the left and right margins of an element, they take up the available horizontal space in the element’s container equally – and thus the element gets centered.
However, this will work for horizontal margins only (more on the why later), and it also won’t work with floated and inline elements and by itself, it also cannot work in absolute and fixed positioned elements (we will however see how to make those work).
Faux Float By Taking Up Available Space
auto in both right and left margins take up the "available" space equally, what do you think will happen when the value
auto is given to only one of those?
A left or right margin with
auto will take up all of the "available" space making the element look like it has been flushed right or left.
“auto” Computed to 0px
As mentioned before,
auto will not work in floated, inline and absolute elements. All these elements already have decided on their layouts, so there is no use in using
auto for the margins and expecting it to get centered just like that.
That will defeat the initial purpose of using something like
auto will have a value of 0px in those elements.
auto will also not work on a typical block element if it doesn’t have a width. All the examples I showed you so far have widths.
A width of value
auto will have
0px margins. A block element’s width typically covers its container’s when it is
100% and hence a margin
auto will be computed to
0px in such a case.
What Happens to Vertical Margins With The Value
auto in both top and bottom margins is always computed to 0px (except for absolute elements). W3C spec says it like this:
“If “margin-top” or “margin-bottom” is “auto”, their used value is 0″
The why, well that is so far, a mystery. It could be because of the typical vertical page flow, where page size increases height-wise. So, centering an element vertically in its container is not going to make it appear centered, relative to the page itself, unlike when it’s done horizontally (in most cases).
And maybe it’s because of this same reason, they decided to add an exception for absolute elements which can be centered vertically along the entire page’s height.
It could also be because of the margin collapse effect (a collapse of adjacent elements” margins) which is another exception for the vertical margins.
However, the latter seems to be an unlikely case – since elements which don’t collapse their margins – like Floats, and elements with
overflow other than
visible, still assign 0px vertical margins for
Centering Absolutely Positioned Elements
Since there happens to be an exception for absolutely positioned elements, we”ll use
auto value to center one vertically and horizontally. But before that, we need to find out when will
margin:auto actually work like we want it to in an absolutely positioned element.
This is where another W3C spec comes in:
"If all three of “left”, “width”, and “right” are “auto”: First set any “auto” values for “margin-left” and “margin-right” to 0… "
"If none of the three is “auto”: If both “margin-left” and “margin-right” are “auto”, solve the equation under the extra constraint that the two margins get equal values"
That pretty much says that for horizontal
auto margins to seize equal spaces, the values for
right shouldn’t be
auto , their default value. So all we have to do is to give them some value in an absolutely positioned element.
right should have equal values for perfect centering.
The spec also mentions something similar for vertical margins.
“If all three of “top”, “height”, and “bottom” are auto, set “top” to the static position…”
“If none of the three are “auto”: If both “margin-top” and “margin-bottom” are “auto”, solve the equation under the extra constraint that the two margins get equal values…”
Hence, for an absolute element to be centered vertically, its
bottom values shouldn’t be
Now by combining all these, this is what we”ll get:
If you ever want to flush an element on your page to right or left without the following elements wrapping it (like whats happens with float), remember there’s the option to use
auto for margins.
Converting an element to absolute just so it can be centered vertically may not be a great idea. There are other options like flexbox and CSS transform which are more suitable for those.