为啥“margin:auto”不垂直居中元素?

Posted

技术标签:

【中文标题】为啥“margin:auto”不垂直居中元素?【英文标题】:Why doesn't "margin: auto" center an element vertically?为什么“margin:auto”不垂直居中元素? 【发布时间】:2016-04-05 18:16:39 【问题描述】:

正如您在下面的演示中所见,margin: auto; 将蓝色 div 水平居中,但不是垂直居中。为什么不呢?

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

我的问题不是寻求解决方法。

【问题讨论】:

它只是没有。水平居中内容的用例可能比垂直居中更常见。 @TZHX 从技术上讲,它可以垂直居中。请参阅此示例 - jsfiddle.net/skdjhpo8 CSS 中的垂直对齐是一个神话 @FabioPoloni Flexbox? @FabioPoloni ¯\_(ツ)_/¯ IE do actually support flexbox 的较新版本,有一些注意事项。 【参考方案1】:

为什么...因为W3C spec 是这么说的。

如果 'margin-top' 或 'margin-bottom' 为 'auto',则它们的使用值为 0。

至于实际的“为什么”……应该在那里真正解决问题。

【讨论】:

【参考方案2】:

如前所述,此行为在 CSS2.1 的 section 10.6.2 中指定,与 CSS2 相比保持不变。

方块盒在正常流程中从上到下垂直堆叠。此外,vertical margins may collapse,并且仅在某些情况下这样做(在您的演示中,父元素上的边框将防止子元素上的任何边距与其自身折叠)。如果你只有一个这样的块框,并且包含块的高度是自动的,那么它的顶部和底部边距无论如何都将为零。但是,如果您在同一个流中有多个块框,或者甚至影响流中框布局的流外框(例如clearance),您希望如何解决自动边距对于那些流入框?

这就是为什么对于内联元素(包括原子内联)和浮动(尽管水平边距永远不会折叠),自动左边距和右边距同样被归零。内联框是laid along line boxes,浮动也服从unique layout rules。

绝对定位的盒子是另一回事:因为它们从不知道与自己处于相同定位上下文中的任何其他盒子,auto top and bottom margins can be calculated for them with respect to their containing blocks 而不必担心任何其他盒子会干扰。

Flexbox 也是一个不同的故事:flex 布局与块布局的不同之处在于,根据定义,flex 项目总是知道同一 flex 格式化上下文中的其他 flex 项目,包括没有的事实。特别是neither can floats intrude into the flex container, nor can you float flex items to subvert this(尽管您仍然可以使用absolute positioning 完全从弹性布局中删除子元素)。弹性项目的边距表现非常不同,部分原因是这一点。请参阅4.2、9.5 和 9.6 部分。

【讨论】:

【参考方案3】:

它不会垂直居中元素,因为它是正常流程中的块级元素。因此,following rule applies:

如果margin-topmargin-bottomauto,则它们的使用值为0。

还值得指出的是,上述规则也适用于以下元素:(有关更多信息和条件,请参阅点 10.6.2 和 10.6.3)。

内联替换元素 正常流程中的块级替换元素 inline-block 替换正常流程中的元素 浮动替换元素 当overflow 计算为visible 时,正常流中的块级非替换元素

话虽如此,绝对定位的、不可替换的元素不具有topheightbottomauto 是此规则的一个例外。以下内容适用于point 10.6.4:

如果topheightbottom这三个都不是auto,并且如果margin-topmargin-bottom都是auto在额外的约束下求解方程两个边距获得相等的值

请参阅下面的示例,演示如何使用margin: 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>

此外,following rule 可能也值得指出:

如果margin-topmargin-bottom 之一是auto,请求解该值的等式。如果值受到过度约束,请忽略 bottom 的值并求解该值。

这意味着如果绝对定位元素的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>

【讨论】:

【参考方案4】:

这是因为知道要在其中垂直居中的元素的真实高度的实际可能性。要理解这一点,首先要考虑自动水平居中的工作原理。你有一个 div,你给它一个宽度(固定或百分比)。宽度可以计算到一定程度。如果它是固定宽度,那就太好了。如果它是灵活的或响应式的(百分比),至少你有一个宽度在到达下一个断点之前将覆盖的范围。你取那个宽度,减去里面的任何东西,然后把剩下的部分分成两边。

现在,有了这些信息,浏览器如何计算出 div 垂直增长的无限变化量?请记住元素的大小、文本的换行、填充和响应性也会改变宽度并迫使文本进一步换行,等等。

这是不可能完成的任务吗?不是真的,CSS 有没有花时间和精力来解决这个问题?不值得他们花时间,我猜。

这基本上就是我告诉我的学生的答案。

但是....不要担心! Bootstrap v4 alpha 发现了vertical centering!

编辑

抱歉编辑得晚了,但我想你可能想考虑这个解决方案垂直居中,使用 calc 函数非常简单

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

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

HERE

【讨论】:

更准确的说法是 Flexbox 已经确定了我们的垂直居中位置,而 B4a 已经赶上了潮流。 那个,我不知道【参考方案5】:

为什么margin:auto 不能垂直工作?

实际上,确实如此——只是不是针对每个 display 值。

如果displayflex,则margin: auto 垂直和水平居中。

这同样适用于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>

【讨论】:

以上是关于为啥“margin:auto”不垂直居中元素?的主要内容,如果未能解决你的问题,请参考以下文章

小tip: margin:auto实现绝对定位元素的水平垂直居中

如何让DIV水平和垂直居中

css实现垂直水平居中的方法(个数不限)?

小tip: margin:auto实现绝对定位元素的水平垂直居中

如何让一个浮动元素既水平又垂直居中

水平居中,垂直居中