保证金与浮动元素折叠 [英] Margin collapsing with floated element

查看:77
本文介绍了保证金与浮动元素折叠的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:以下行为在Firefox上不可见。



让我们从以下情况开始:

html {background:red;} body {margin :0;最小高度:100vh; background-color:green;} div {min-height:50px; background-color:pink; margin-bottom:50px;}

< div>< ; / div>



$ c> min-height:100vh ,我们有一个滚动条让我们看到 html 。在这里,我们有一个边距折叠 div 的边距与主体边距一起折叠,因此在主体和滚动条。



如果我们引用


两个边距是相邻的当且仅当:

p>

...



最后一个流入子元素的底部边距和其父元素的底部边距
如果父母有'自动'计算出的身高

div last in-flow 元素和 body 具有height auto,因为我们只指定了min-height。



< hr>

现在让我们添加更多可能受此边距影响的元素,并保留边距合并规则。做到这一点的唯一方法是添加浮动元素,以使我们的 div 总是最后一个流入元素。



以下是新代码:

  html {background:red;} body {margin:0;最小高度:100vh; background-color:green;} div {min-height:50px; background-color:pink; margin-bottom:50px;}。l {width:45%;高度:50像素;向左飘浮; margin:0;}。r {width:45%;高度:50像素;浮动:权利; margin:0;}  

< div>< / div>< div class =l>< / div>< div class =r>< / div>

正如我们可以清楚地看到的,我们仍然有边缘崩溃(因为滚动),并且浮动元素也被相同量的所以我的问题是:为什么会有这种行为?




我对边缘折叠的理解是,最终我们只会在某处应用一个一个边距。通过添加新元素,我预计会出现以下两种情况之一:


  1. 添加浮动元素将以某种方式取消边距折叠< (这不可能是这种情况,因为我们没有违反任何规则)

  2. 浮动元素不会受边距的影响,因为这个浮动元素会随着身体边距而折叠,因此移动/应用于身体。






在规范中,我还发现了这个 complex 语句:


请注意,
对其他元素的位置没有影响,而其他元素的位置正在崩溃;

我从上面了解到,上面的边框位置只需要
来铺设这些元素的后代。其他元素不会受到边缘折叠的影响,从而保持其初始位置,这就解释了浮动元素被压下的原因。





$ b $(我不确定这是否是这种情况) b

如果这是解释,那对我来说有点混乱和不合逻辑。我添加了一个边距,并且最终得到了两个清晰可见的边距。为什么这样的行为?或者,也许我错过了规范中的一些内容,而且我们所面临的不仅仅是一个简单的保证金折叠? b
$ b b em>重要提示
:在回答之前,请注意我没有在寻找解决方法或如何避免此问题。我知道至少有5种方法可以取消边缘折叠(填充,溢出,边框,柔性盒等)。我期待了解为什么会发生这种情况。






参考此问题其中 @Alohci 突出显示这在我的答案和几个评论后,我们都没有确信 解决方案

在我开始之前,问题的滚动条在所有浏览器中呈现,但Firefox与这里所询问的内容不同。当父母的 min-height 导致边距不相邻时,Firefox不会折叠父元素与其子元素之间的边距。 这也是Firefox已知的规范违规行为,目前正在开发中以解决问题。



现在谈谈这个问题。从9.5.1节(浮点数):



  1. 浮动框的外顶可以不要高于其包含块的顶部。当浮动发生在两个折叠边界之间时,浮点的位置就好像它有一个参与流程的空的匿名块父节点。此类父母的位置由保证金折叠部分中的规则定义。


这句话中的最后一句话很尴尬,但规则指的是(通过链接)崩溃的定义。虽然您从该部分引用的具体文本是相关的,但它并不能解释为什么浮动元素会尊重流入 div 的边距。



这样做:


如果框的顶部和底部边距相邻,则可以利润率将通过它崩溃。在这种情况下,元素的位置取决于其与边缘被折叠的其他元素的关系。


  • [。否则,元素的父元素不参与边距折叠,或者只涉及父元素的底部边距。元素上边框的位置与元素底边非零时的位置相同。





请注意最后一句。如你所知,有一个非零的底部边框可以取消边缘折叠。这意味着浮动的位置就好像流入中的 div body 元素没有崩溃,导致浮动出现在流入 div 的底部空白处。



我怎么知道浮游物特别尊重流入中的 div 不是折叠保证金的底部边距?通过给 body 一个比流入中的 div 更大的下边距,并且观察到它不影响位置的浮点数:



html {background:red; } body {margin:0; margin-bottom:100px;最小高度:100vh; background-color:green;} div {min-height:50px; background-color:pink; margin-bottom:50px;}。l {width:45%;高度:50像素;向左飘浮; margin:0;}。r {width:45%;高度:50像素;浮动:权利; margin:0;}

< div>< / div>< div class =l>< / div>< div class =r>< / div>


Update: the below behavior is not visible on Firefox.

Let's start with the following situation:

html {
  background: red;
}

body {
  margin: 0;
  min-height: 100vh;
  background-color: green;
}

div {
  min-height: 50px;
  background-color: pink;
  margin-bottom: 50px;
}

<div></div>

The body is defined with a min-height:100vh and we have a scroll bar that allow us to see the html. Here we are having a margin-collapsing, the margin of the div is collapsed with the body margin and thus create this space after the body and the scroll bar.

If we refer to the specification we have this case:

Two margins are adjoining if and only if:

...

bottom margin of a last in-flow child and bottom margin of its parent if the parent has 'auto' computed height

the div is the last in-flow element and body has height auto as we only specified min-height.


Now let's add more elements that may be affected by this margin and keep the rules of margin-collapsing. The only way to do this is to add floated elements to keep our div always the last in-flow element.

Here is the new code:

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>

As we can clearly see, we still have margin collapsing (because of the scroll) AND the floated elements are also pushed down by the same amount of the margin.

So my question is: why such behavior?


My understanding of margin-collapsing is that at the end we will have only one margin applied somewhere. By adding new elements, I am expecting to have one of this two situations:

  1. Adding the floated elements will somehow cancel the margin-collapsing (this cannot be the case as we are not breaking any rule)
  2. The floating elements will not get affected by the margin as this one collapsed with body margin and thus moved/applied to the body. (This is a logic case for me)


In the specification I also found this complex statement:

Note that the positions of elements that have been collapsed through have no effect on the positions of the other elements with whose margins they are being collapsed; the top border edge position is only required for laying out descendants of these elements.

I understand from the above that the other elements get not affected by the margin-collapsing and thus keep their initial position which explain why the floated elements are pushed down. (I am not sure if this is the case by the way)


If this is the explanation then it's a bit confusing and illogical for me. I added one margin and I end up having two margins that are clearly visible??

So why such behavior? Or maybe I missed something in the specification and we are facing more than a simple margin-collapsing?


Important notice: Before answering, please note that I am not looking for a fix to this or how to avoid this. I know at least 5 ways to cancel margin-collapsing (padding, overflow, border, flexbox,etc..).I am looking to understand why such thing happen.


For the reference: this started by this question where @Alohci highlighted this in my answer and after few comments we both didn't get convinced

解决方案

Before I start, the issue of scrollbars being rendered in all browsers but Firefox is a separate issue from what is being asked about here. Firefox does not collapse margins between a parent element and its children when the parent's min-height results in the margins not being adjoining. It's also a known spec violation in Firefox that's being worked on and yet to be fixed.

Now, on to the issue at hand. From section 9.5.1 (on floats):

  1. A floating box's outer top may not be higher than the top of its containing block. When the float occurs between two collapsing margins, the float is positioned as if it had an otherwise empty anonymous block parent taking part in the flow. The position of such a parent is defined by the rules in the section on margin collapsing.

The last sentence in this quote is awkward, but "the rules" refer (and link) to the definition of collapsing through. While the specific text that you cite from that section is relevant, it doesn't explain why the floats respect the margin of the in-flow div.

This does:

If the top and bottom margins of a box are adjoining, then it is possible for margins to collapse through it. In this case, the position of the element depends on its relationship with the other elements whose margins are being collapsed.

  • [...]

  • Otherwise, either the element's parent is not taking part in the margin collapsing, or only the parent's bottom margin is involved. The position of the element's top border edge is the same as it would have been if the element had a non-zero bottom border.

Note the last sentence. Having a non-zero bottom border cancels margin collapsing, as you know. This means that the floats are positioned as if the bottom margins of the in-flow div and the body element did not collapse, resulting in the floats appearing to respect the bottom margin of the in-flow div.

How do I tell that the floats specifically respect the bottom margin of the in-flow div and not the collapsed margin? By giving body a larger bottom margin than that of the in-flow div and observing that it does not affect the position of the floats:

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>

这篇关于保证金与浮动元素折叠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆