更新 :以下行为在Firefox上不可见。
让我们从以下情况开始:
html { background: red; } body { margin: 0; min-height: 100vh; background-color: green; } div { min-height: 50px; background-color: pink; margin-bottom: 50px; } <div></div>
主体用定义,min-height:100vh我们有一个滚动条,让我们可以看到html。在这里,我们有一个 margin-colapsing ,边距div与主体边距一起折叠,从而在主体和滚动条之后创建此空间。
min-height:100vh
html
div
如果我们参考规范,则有这种情况:
当且仅当以下情况,两个边距相邻: … 最后一个流入子项的底边距及其父项的底边距(如果父级具有“自动”计算的高度)
当且仅当以下情况,两个边距相邻:
…
最后一个流入子项的底边距及其父项的底边距(如果父级具有“自动”计算的高度)
该元素div是 最后一个流入 元素,并且body具有高度自动值,因为我们仅指定了最小高度。
body
现在,让我们添加更多可能受此边距影响的元素,并保留边距折叠规则。唯一的方法是添加 浮动 元素,以使我们div始终是最后一个流入元素。
这是新代码:
html { background: red; } body { margin: 0; min-height: 100vh; background-color: green; } div { min-height: 50px; background-color: pink; margin-bottom: 50px; } .l { width:45%; height:50px; float:left; margin:0; } .r { width:45%; height:50px; float:right; margin:0; } <div></div> <div class="l"></div> <div class="r"></div>
正如我们可以清楚地看到的那样,由于滚动的缘故,我们仍然有边际崩溃,并且浮动元素也被下压了相同数量的边际。
所以我的问题是: 为什么会这样?
我对保证金崩溃的理解是,最后,我们将仅在某处应用 一个 保证金。通过添加新元素,我期望会出现以下两种情况之一:
在规范中,我还发现了以下 复杂 语句:
请注意,已折叠的元素的位置对其他以其边距折叠的元素的位置没有影响;仅在布置这些元素的后代时才需要顶部边框边缘位置。
从以上内容可以理解,其他元素不受边界收缩的影响,因此保持其初始位置,这解释了为什么浮动元素被向下推。 (我不确定是否是这种情况)
如果这是解释,那么对我来说有点混乱和不合逻辑。我增加了 一个 边距,最后却有 两个 清晰可见的边距?
那么为什么会这样呢?还是我错过了规范中的某些内容,而我们所面临的不仅仅是简单的边际崩溃?
重要提示 :在回答之前,请注意,我不是在寻求解决此问题的方法,也不希望如何避免此问题。我知道至少有5种方法可以取消边距折叠(填充,溢出,边框,弹性框等)。我想了解为什么会发生这种情况。
供参考 :这是从这个问题开始的,@Alohci在我的回答中突出了这一点,经过几番评论,我们俩都没有被说服
在我开始之前,所有浏览器中都会呈现滚动条的问题,但Firefox是一个与此处所询问的问题不同的问题。当父元素与其子元素之间min-height的边距不相邻时,Firefox不会折叠其父元素与其子元素之间的边距。在Firefox中,这也是已知的违反规范的问题,目前仍在解决,尚待解决。
min-height
现在,讨论当前的问题。从第9.5.1节开始(关于浮动):
4. 浮动框的外部顶部不得高于其包含的块的顶部。当浮动发生在两个折叠边距之间时,浮动的位置就好像是有一个空的匿名块父级参与了流程。这样的父母的位置由保证金崩溃部分中的规则定义。
该引号中的最后一句很尴尬,但是“规则”是指(和链接)崩溃的定义。虽然您从该部分引用的特定文本是相关的,但并未说明浮动内容为何尊重流入量的余量div。
这样做:
如果框的顶部和底部边距相邻,则边缘可能会通过它塌陷。在这种情况下,元素的位置取决于其与其边距被折叠的其他元素的关系。 […] 否则,要么元素的父级不参与边距崩溃,要么仅涉及父级的底边距。元素的顶部边框边缘的位置与元素的底部边框非零时的位置相同。
如果框的顶部和底部边距相邻,则边缘可能会通过它塌陷。在这种情况下,元素的位置取决于其与其边距被折叠的其他元素的关系。
[…]
否则,要么元素的父级不参与边距崩溃,要么仅涉及父级的底边距。元素的顶部边框边缘的位置与元素的底部边框非零时的位置相同。
注意最后一句话。如您所知,底部边框不为零将消除边距折叠。这意味着浮子的位置就好像流入流的底部边缘div并且body元素 没有 塌陷,导致浮子似乎尊重流入流的底部边缘div。
我如何知道浮标专门考虑流入量的底边div而 不是 倒塌边?通过提供body比流入流量更大的底边距,div并观察它不会影响浮子的位置,请执行以下操作:
html { background: red; } body { margin: 0; margin-bottom: 100px; min-height: 100vh; background-color: green; } div { min-height: 50px; background-color: pink; margin-bottom: 50px; } .l { width:45%; height:50px; float:left; margin:0; } .r { width:45%; height:50px; float:right; margin:0; } <div></div> <div class="l"></div> <div class="r"></div>