为啥“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-top
或margin-bottom
是auto
,则它们的使用值为0。
还值得指出的是,上述规则也适用于以下元素:(有关更多信息和条件,请参阅点 10.6.2 和 10.6.3)。
内联替换元素 正常流程中的块级替换元素inline-block
替换正常流程中的元素
浮动替换元素
当overflow
计算为visible
时,正常流中的块级非替换元素
话虽如此,绝对定位的、不可替换的元素不具有top
、height
和bottom
值auto
是此规则的一个例外。以下内容适用于point 10.6.4:
如果
top
、height
和bottom
这三个都不是auto
,并且如果margin-top
和margin-bottom
都是auto
,在额外的约束下求解方程两个边距获得相等的值。
请参阅下面的示例,演示如何使用margin: auto
将绝对定位元素垂直居中。之所以有效,是因为top
、height
和 bottom
三个属性都没有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-top
或margin-bottom
之一是auto
,请求解该值的等式。如果值受到过度约束,请忽略bottom
的值并求解该值。
这意味着如果绝对定位元素的margin-top
值为auto
和margin-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
值。
如果display
是flex
,则margin: auto
垂直和水平居中。
这同样适用于display: inline-flex
、display: grid
和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>
【讨论】:
以上是关于为啥“margin:auto”不垂直居中元素?的主要内容,如果未能解决你的问题,请参考以下文章
小tip: margin:auto实现绝对定位元素的水平垂直居中