Why doesn't margin: auto center the element vertically?

As you can see in the demo below, margin: auto; centers the blue div horizontally, but not vertically. Why not?

 .box { border: 1px solid red; width: 100px; height: 100px; } .center { background: blue; width: 50px; height: 50px; margin: auto; } 
 <div class="box"> <div class="center"></div> </div> 

My question does not require workarounds.

+44
html css margin
Dec 31 '15 at 22:30
source share
5 answers

As already mentioned, this behavior is specified in section 10.6.2 in CSS2.1 and remains unchanged from CSS2 .

The blocks are stacked vertically from top to bottom in normal flow. In addition, vertical fields can collapse and do this only under certain circumstances (in your demonstration, the border on the parent will prevent any fields on the child from collapsing with its own). If you have only one such block, and the height of the containing block will be automatically, then its upper and lower fields will be zero. But if you have more than one block in the same stream or even outside of stream boxes that affect the location of the fields in the stream (in the case of clearance ), how would you expect automatic fields to be allowed for those in the stream?

This is why the automatic left and right fields are also nullified for inline elements (including atomic strings) and floats (although horizontal fields never crash). The string cabinets fit along linear blocks and swims to obey the unique layout rules too.

Absolutely positioned fields are different stories: since they never know about any other boxes in the same positioning context as they, auto upper and lower fields can be calculated for them in relation to their containing blocks , without worrying about any or other cases ever disturbing.

Flexbox also has a different story: what sets a flexible layout different from a block layout is that flex elements by definition always know about other flex elements in the same context of flex formatting, including that there is none of them. In particular, none of them can be moved into the flex container, and you cannot float flexible elements to undermine this (although you can still remove the child from the flexible scheme completely with absolute positioning ). Margin behaves differently with flexible elements because of this. See Sections 4.2 , 9.5, and 9.6 .

+33
Dec 31 '15 at 22:58
source share

Why ... because the W3C spec says it.

If "margin-top" or "margin-bottom" are "auto", their usable value is 0.

As for the actual "why" ... the question really needs to be addressed there.

+30
Dec 31 '15 at 22:41
source share

It does not center the element vertically because it is a block level element in a normal flow. Therefore, the following rule applies:

If margin-top or margin-bottom are auto , their used value is 0.

It is also worth noting that the above rule also applies to the following elements: (see paragraphs 10.6.2 and 10.6.3 for more information and conditions).

  • Inline elements
  • Elements with block level substitution in normal flow
  • inline-block replaced elements in normal flow
  • Floating replaceable items
  • Block-level non-replaceable elements in normal flow when overflow calculates visible

With that said, absolutely excluded elements that do not have the values top , height and bottom auto are an exception to this rule. The following applies to clause 10.6.4 :

If none of the three top , height and bottom is auto , and if both margin-top and margin-bottom are auto , they solve the equation under an additional constraint, the two fields get equal values .

See the example below for a demonstration of how an absolutely positioned element is vertically centered using margin: auto . It works because none of the three top , height and bottom properties have an auto value:

 .box { border: 1px solid red; width: 100px; height: 100px; position: relative; } .center { background: blue; width: 50px; height: 50px; margin: auto; position: absolute; top: 0; right: 0; bottom: 0; left: 0; } 
 <div class="box"> <div class="center"></div> </div> 

In addition, you should probably specify the following rule :

If one of margin-top or margin-bottom is auto , solve the equation for that value. If the values ​​are exceeded, ignore the value for bottom and decide for this value.

This means that if an absolutely positioned element has a margin-top auto value and a margin-bottom value of 0 (i.e. margin: auto auto 0 ), the element will be absolutely located at the bottom relative to the parent, as in the example below:

 .box { border: 1px solid red; width: 100px; height: 100px; position: relative; } .center { background: blue; width: 50px; height: 50px; margin: auto auto 0; position: absolute; top: 0; right: 0; bottom: 0; left: 0; } 
 <div class="box"> <div class="center"></div> </div> 
+16
Dec 31 '15 at 23:02
source share

Why doesn't margin:auto work vertically?

In fact, this happens - just not for every display value.

If display flex , margin: auto centered both vertically and horizontally.

The same goes for display: inline-flex , display: grid and display: inline-grid .

 .box { border: 1px solid red; width: 100px; height: 100px; display: flex; /* new */ } .center { background: blue; width: 50px; height: 50px; margin: auto; } 
 <div class="box"> <div class="center"></div> </div> 
+13
Dec 31 '15 at 23:36
source share

This is because of the real opportunity to find out the true height of the element in which you want to center vertically. To understand this, first think about how automatic horizontal centering works. You have a div that you gave it the width (fixed or percentage). Width can be calculated to a certain extent. If a fixed width, great. If it is flexible or responsive (in percent), at least you have a range that will span the width before it reaches the next breakpoint. You take this width, minus everything inside, and divide the remainder on both sides.

Now, with this information, how could the browser calculate an infinite number of variations in which your div will grow vertically? Keep in mind that element size, text wrapping, paddings, and responsiveness will also change the width and make the text look farther and farther and farther on it.

Is this an impossible task? In fact, CSS has spent time and effort on this? Probably not worth their time.

And this is basically the answer that I am telling my students.

But ... don’t worry! Bootstrap v4 alpha calculated vertical centering !

EDIT

Sorry to edit this late, but I thought you might want to consider this solution in order to center vertically, and it's pretty simple using calc function

 <div class="foo"></div> .foo { background-color: red; height: 6em; left: calc(50% - 3em); position: absolute; top: calc(50% - 3em); width: 6em; } 

See HERE

+3
Dec 31 '15 at 23:05
source share



All Articles