简体   繁体   English

为什么“margin:auto”不是垂直居中的元素?

[英]Why doesn't “margin: auto” center an element vertically?

As you can see in the demo below, margin: auto; 正如您在下面的演示中所看到的, margin: auto; centers the blue div horizontally, but not vertically. 将蓝色div水平居中,但不垂直居中。 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 is not asking for workarounds. 我的问题不是要求解决方法。

As mentioned, this behavior is specified in section 10.6.2 of CSS2.1, and has remained unchanged from CSS2 . 如上所述,此行为在CSS2.1的第10.6.2节中指定,并且与CSS2保持不变。

Block boxes are stacked vertically from top to bottom in normal flow. 在正常流动中,块箱从顶部到底部垂直堆叠。 Furthermore, vertical margins may collapse , and only do so under certain circumstances (in your demo, the border on the parent element will prevent any margins on the child element from collapsing with its own). 此外, 垂直边距可能会崩溃 ,并且只在某些情况下才会崩溃 (在演示中,父元素上的边框将阻止子元素上的任何边距与其自身折叠)。 If you only have one such block box, and the height of the containing block is auto, then its top and bottom margins will be zero anyway. 如果你只有一个这样的块盒,并且包含块的高度是auto,那么它的顶部和底部边距无论如何都将为零。 But if you have more than one block box in the same flow, or even out-of-flow boxes affecting the layout of in-flow boxes (in the case of clearance for example), how would you expect auto margins to resolve for those in-flow boxes? 但是,如果在同一流程中有多个块框,或者甚至是影响流入框布局的流出框(例如,在清除的情况下),您希望如何为这些框解决自动边距流入箱?

This is why auto left and right margins are likewise zeroed out for inline elements (including atomic inlines) and floats (though horizontal margins never collapse). 这就是为什么自动左右边距同样归零为内联元素(包括原子内联)和浮点数(尽管水平边距永不崩溃)。 Inline-level boxes are laid along line boxes , and floats too obey unique layout rules . 内联级框沿线框放置 ,浮动也遵循独特的布局规则

Absolutely positioned boxes are a different story: since they are never aware of any other boxes in the same positioning context as themselves, auto top and bottom margins can be calculated for them with respect to their containing blocks without having to worry about any other boxes ever interfering. 绝对定位的盒子是一个不同的故事:因为他们从来没有意识到与自身相同的定位环境中的任何其他盒子,所以可以针对它们的包含块计算自动顶部和底部边距,而不必担心任何其他盒子干扰。

Flexbox is also a different story: what sets flex layout apart from block layout is that flex items are by definition always aware of other flex items in the same flex formatting context, including the fact that there are none. Flexbox也是一个不同的故事:将flex布局与块布局区分开来的是,flex项目根据定义始终知道同一个flex格式化上下文中的其他flex项目,包括没有的事实。 In particular, neither can floats intrude into the flex container, nor can you float flex items to subvert this (although you can still remove a child element from flex layout completely with absolute positioning ). 特别是, 既不能浮动进入Flex容器,也不能浮动flex项来破坏它 (尽管你仍然可以通过绝对定位完全从flex布局中移除子元素)。 Margins behave very differently with flex items due in part to this. 由于部分原因,边距与弹性项目的表现非常不同。 See sections 4.2 , 9.5 and 9.6 . 见第4.29.59.6

Why...because the W3C spec says so. 为什么......因为W3C规范是这么说的。

If 'margin-top', or 'margin-bottom' are 'auto', their used value is 0. 如果'margin-top'或'margin-bottom'为'auto',则其使用值为0。

As to the actual "why"...the query should really be addressed there. 至于实际的“为什么”......那里的查询应该真正得到解决。

It doesn't center the element vertically because it is a block-level element in the normal flow. 它不会垂直居中元素,因为它是正常流程中的块级元素。 Thus, the following rule applies : 因此, 以下规则适用

If margin-top , or margin-bottom are auto , their used value is 0. 如果margin-topmargin-bottomauto ,则其使用值为0。

It's also worth pointing out that the rule above also applies to the following elements as well: (see points 10.6.2 and 10.6.3 for more information and conditions). 值得指出的是,上述规则也适用于以下要素:(有关更多信息和条件,请参见第10.6.210.6.3节 )。

  • Inline replaced elements 内联替换元素
  • Block-level replaced elements in normal flow 正常流程中的块级替换元素
  • inline-block replaced elements in normal flow inline-block在正常流程中替换了元素
  • Floating replaced elements 浮动替换元素
  • Block-level non-replaced elements in normal flow when overflow computes to visible overflow计算为visible时,正常流程中的块级非替换元素

With that being said, absolutely positioned, non-replaced elements that don't have top , height , and bottom values of auto are an exception to this rule. 话虽如此,绝对定位,没有auto topheightbottom值的非替换元素是这个规则的一个例外。 The following applies from point 10.6.4 : 以下适用于第10.6.4点

If none of the three top , height , and bottom are auto and if both margin-top and margin-bottom are auto , solve the equation under the extra constraint that the two margins get equal values . 如果三个topheightbottom都不是auto并且如果margin-topmargin-bottom都是auto则在额外约束条件下求解两个边距得到相等值的等式

See the example below demonstrating how an absolutely positioned element is vertically centered using margin: auto . 请参阅下面的示例,演示绝对定位元素如何使用margin: auto垂直居中。 It works because none of the three properties top , height , and bottom have a value of auto : 它的工作原理是因为topheightbottom这三个属性都没有auto值:

 .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, it's probably worth pointing out the following rule as well: 此外,它可能值得指出以下规则

If one of margin-top or margin-bottom is auto , solve the equation for that value. 如果margin-topmargin-bottomauto ,则求解该值的等式。 If the values are over-constrained, ignore the value for bottom and solve for that value. 如果值过度约束,则忽略bottom的值并求解该值。

This means that if the absolutely positioned element has a margin-top value of auto and a margin-bottom value of 0 (ie, margin: auto auto 0 ), the element would be absolutely positioned at the bottom relative to the parent like in the example below: 这意味着如果绝对定位元素的margin-top值为automargin-bottom值为0 (即margin: auto auto 0 ),则该元素将绝对位于相对于父元素的底部,如示例如下:

 .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> 

Why doesn't margin:auto work vertically? 为什么没有margin:auto垂直工作?

Actually, it does – just not for every display value. 实际上,它确实 - 只是不是每个display值。

If display is flex , margin: auto centers both vertically and horizontally. 如果displayflex ,则margin: auto垂直和水平居中。

The same applies to display: inline-flex , display: grid and display: inline-grid . 这同样适用于display: inline-flexdisplay: griddisplay: 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> 

It's because of the actual possibility of knowing the true height of the element in which you want to center vertically in. To understand that, first think about how auto horizontal centering works. 这是因为实际可能知道要垂直居中的元素的真实高度。要理解这一点,首先要考虑自动水平居中的工作原理。 You have a div which you've given it a width (fixed or percentage). 你有一个div,你给它一个宽度(固定或百分比)。 The width can be calculated to certain degree. 可以在一定程度上计算宽度。 If it's fixed width, great. 如果是固定宽度,很棒。 If it's flexible or responsive (percentage) at least you have a range that the width will cover before it hits the next breakpoint. 如果它的灵活性或响应性(百分比)至少你有一个宽度将覆盖到下一个断点之前的范围。 You take that width, minus whatever it's inside and split the remainder on both sides. 你取宽度,减去它内部的任何宽度,然后将两侧的剩余部分分开。

Now, with that information, how could the browser calculate the infinite amount of variations in which your div will grow vertically? 现在,有了这些信息,浏览器如何计算div将垂直增长的无限变化量? Keep in mind the size of the element, wrapping of text, paddings, and responsiveness will also alter the width and force the text to wrap further, and on, and on it goes. 请记住元素的大小,文本的包装,填充和响应性也会改变宽度,并强制文本进一步包装,然后打开,然后继续。

Is it an impossible task? 这是一项不可能的任务吗? Not really, has CSS spent time and effort covering this? 不是真的,CSS花费了时间和精力来解决这个问题吗? Not worth their time, I guess. 我猜,不值得他们的时间。

And that is basically the answer I tell my students. 这基本上是我告诉我的学生的答案。

But....fret not! 但是......不要担心! Bootstrap v4 alpha has figured out vertical centering ! Bootstrap v4 alpha已经找到了垂直居中

EDIT 编辑

Sorry to edit this late but I thought you may want to consider this solutions to center vertically and it is pretty simple by making use of the calc function 很抱歉编辑这个很晚但我觉得你可能想要考虑这个解决方案垂直居中,通过使用calc函数非常简单

<div class="foo"></div>

.foo {
  background-color: red;
  height: 6em;
  left: calc(50% - 3em);
  position: absolute;
  top: calc(50% - 3em);
  width: 6em;
}

See it HERE 看到这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM