css 为什么不“保证金:自动将元素垂直居中?

l0oc07j2  于 2023-02-10  发布在  其他
关注(0)|答案(6)|浏览(112)

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

我的问题不是要求变通办法。

qyswt5oh

qyswt5oh1#

如前所述,此行为在CSS2.1的第10.6.2节中指定,与CSS2相比保持不变。
积木盒在正常流程中是从上到下垂直堆叠的。此外,垂直边距可能会折叠,并且只有在某些情况下才会折叠(在您的演示中,父元素上的边框将防止子元素上的任何边距与其自己的边距折叠在一起)。如果您只有一个这样的块框,并且包含块的高度为auto,那么它的顶部和底部边距将为零。但是如果您在同一个流中有多个块框,或者甚至流出框影响流入框的布局(例如,在清除的情况下),您将如何期望自动边距解决这些流入框的问题?
这就是为什么自动左、右边距也会为内联元素(包括原子内联)和浮动(尽管水平边距永远不会折叠)清零的原因。内联级别的框沿着行框放置,浮动也遵循独特的布局规则。
绝对定位的盒子则是另一回事:由于它们从不知道在与它们相同的定位上下文中有任何其它框,因此可以相对于它们的包含块为它们计算自动顶部和底部边距,而不必担心任何其它框会干扰。
Flexbox也是一个不同的故事:Flex布局与块布局的不同之处在于,Flex项根据定义总是知道相同Flex化上下文中的其他Flex项,包括没有Flex项的事实。特别地,浮动既不能侵入Flex容器,您也不能浮动弹性项目来破坏这一点(尽管您仍然可以使用绝对定位从Flex布局中完全删除子元素)。部分由于此原因,Flex项目的边距表现非常不同。参见第4.2、9.5和9.6节。

wnavrhmk

wnavrhmk2#

为什么...因为W3C规范这么说。
如果“margin-top”或“margin-bottom”为“auto”,则它们的使用值为0。
至于实际的“为什么”...质疑真的应该在那里解决。

fslejnso

fslejnso3#

它不会使元素垂直居中,因为它是正常流中的块级元素。因此,以下规则适用:
如果margin-topmargin-bottomauto,则它们的使用值为0。
同样值得指出的是,上述规则也适用于以下元素:(有关更多信息和条件,请参见第10.6.2和10.6.3点)。

  • 内联替换元素
  • 正常流中块级替换元素
  • inline-block正常流量下更换的元件
  • 浮动替换元素
  • overflow计算为visible时,正常流中的块级未替换元素

也就是说,绝对定位的、不可替换的元素,如果topheightbottom的值不等于auto,则是这个规则的一个例外。
如果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>

此外,以下规则或许也值得一提:
如果margin-topmargin-bottom之一为auto,则求解方程以获得该值。如果这些值过度约束,则忽略bottom的值并求解该值。
这意味着,如果绝对定位元素的margin-top值为automargin-bottom值为0(即margin: auto auto 0),则该元素将绝对定位在相对于父元素的底部,如下例所示:
一个二个一个一个

qxgroojn

qxgroojn4#

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

tnkciper5#

这是因为我们有可能知道要垂直居中的元素的真实高度。要理解这一点,首先考虑一下自动水平居中是如何工作的。(固定或百分比),宽度可以进行一定程度的计算,如果是固定宽度,很好。如果它是灵活的或者响应性很强的(百分比),那么至少在它到达下一个断点之前,你有一个宽度可以覆盖的范围。你取这个宽度,减去它里面的任何东西,然后把剩下的部分在两边分开。
现在,有了这些信息,浏览器如何计算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

f4t66c6m

f4t66c6m6#

上面的代码不适用于垂直对齐的原因是边距:auto 0只能使子div水平居中,而不能垂直居中。边距:auto属性通过在两边平均分配剩余空间来水平居中元素,但是垂直居中没有等效的属性。要垂直居中子div,您需要使用其他方法,如绝对定位、弹性框或网格。

相关问题