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

时间:2015-12-31 22:30:29

标签: html css margin

正如您在下面的演示中所看到的,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>

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

5 个答案:

答案 0 :(得分:36)

如上所述,此行为在CSS2.1的section 10.6.2中指定,并且与CSS2保持不变。

在正常流动中,块箱从顶部到底部垂直堆叠。此外,vertical margins may collapse,并且仅在某些情况下这样做(在您的演示中,父元素上的边框将阻止子元素上的任何边距与其自身折叠)。如果你只有一个这样的块盒,并且包含块的高度是auto,那么它的顶部和底部边距无论如何都将为零。但是,如果在同一流程中有多个块框,或者甚至是影响流入框布局的流出框(例如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完全从flex布局中删除子元素)。由于部分原因,边距与弹性项目的表现非常不同。请参阅4.29.59.6部分。

答案 1 :(得分:30)

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

  

如果'margin-top'或'margin-bottom'为'auto',则其使用值为0.

至于实际的“为什么”...这个问题应该真正解决。

答案 2 :(得分:16)

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

  

如果margin-topmargin-bottomauto,则其使用值为0.

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

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

话虽如此,绝对定位,不具备topheightbottom auto值的未替换元素是个例外遵守这条规则。以下内容适用于point 10.6.4

  

如果三个topheightbottom都不是automargin-topmargin-bottom都是{{1} }},在额外约束下求解方程,即两个边距得到相等的值

请参阅下面的示例,演示绝对定位元素如何使用auto垂直居中。它有效,因为margin: autotopheight三个属性都没有bottom的值:

&#13;
&#13;
auto
&#13;
.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;
}
&#13;
&#13;
&#13;

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

  

如果<div class="box"> <div class="center"></div> </div>margin-top中的某个margin-bottomauto,则求解该值的等式。如果值过度约束,请忽略bottom的值并求解该值。

这意味着,如果绝对定位元素的margin-top值为automargin-bottom值为0(即margin: auto auto 0),则element将绝对位于相对于父级的底部,如下例所示:

&#13;
&#13;
.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;
}
&#13;
<div class="box">
  <div class="center"></div>
</div>
&#13;
&#13;
&#13;

答案 3 :(得分:13)

  

为什么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>

答案 4 :(得分:3)

这是因为实际上可能知道要垂直居中的元素的真实高度。要理解这一点,首先要考虑自动水平居中的工作原理。你有一个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