块格式化上下文,折叠边距和浮动容器 [英] Block Formatting Contexts, Collapsing Margins and Floating Containers

查看:97
本文介绍了块格式化上下文,折叠边距和浮动容器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了理解块格式化上下文是做什么的,我试图找出BFC 创建时发生了什么。



我从关于Clearfix的所有知识都是错误



.wrapper {width :740px;背景:#cccccc;}。leftSidebar {float:left; width:200px;}。rightSidebar {float:right; width:200px;}。mainContent {padding-right:200px; padding-left:200px;}。floatMe {float:left;背景:蓝绿色; color:#fff;}

< div class =包装> < div class =leftSidebar> < H2>标题< / H2> < pre> .leftSidebar {float:left;宽度:200像素;}< /预> < / DIV> < div class =rightSidebar> < H2>标题< / H2> < pre> .rightSidebar {float:right;宽度:200像素;}< /预> < / DIV> < div class =mainContent> < H2>标题< / H2> < pre> ;.mainContent {padding-right:200px;填充左:200像素;}< /预> < div class =floatMe> < pre> .floatMe {float:left;背景:水鸭;颜色:#FFF;}< /预> < / DIV> < / div>< / div>

文章(重点介绍):


在现代浏览器中:

所有元素都属于相同的块格式上下文,因此相邻的
页边距折叠。标题的边距贴出包装到
对照 p 。与IE不同的是,这个保证金(不是在黑箱上的
上的保证金)会在包装上面产生差距。


我无法理解同一个块格式化上下文是指什么。我想知道为什么这样一个奇怪的布局没有块格式上下文产生。



我试图找出确切的布局,通过添加 * {border:1px solid blue;} to CSS,但整体布局在改变之后发生了很大的变化:现在它的行为如同 wrapper 块格式化上下文!



.wrapper {width:740px;背景:#cccccc;}。leftSidebar {float:left; width:200px;}。rightSidebar {float:right; width:200px;}。mainContent {padding-right:200px; padding-left:200px;}。floatMe {float:left;背景:蓝绿色; color:#fff;} * {border:1px solid blue;}

< div class =wrapper> < div class =leftSidebar> < H2>标题< / H2> < pre> .leftSidebar {float:left;宽度:200像素;}< /预> < / DIV> < div class =rightSidebar> < H2>标题< / H2> < pre> .rightSidebar {float:right;宽度:200像素;}< /预> < / DIV> < div class =mainContent> < H2>标题< / H2> < pre> ;.mainContent {padding-right:200px;填充左:200像素;}< /预> < div class =floatMe> < pre> .floatMe {float:left;背景:水鸭;颜色:#FFF;}< /预> < / DIV> < / div>< / div>

发生了什么事情。

解决方案

好问题,让我想到了很多!



这里有很多概念,所以我会一一找到他们。

Buggy IE

p>

无论在 hasLayout 属性造成的。 此MSDN文档适用于IE7:


什么是HasLayout?为什么它很重要?
$ b
Internet Explorer中存在一些错误通过在元素上强制布局(一个
IE内部数据结构)来解决这个问题。


显然,这是一个非标准的解决方法,并伴随着很多不一致。请阅读此此处



<
块格式化上下文(BFC)


摘自本MDN文档


块格式上下文是
网页的可视化CSS渲染的一部分。在这个区域,块盒的布局出现在
中,而浮动块之间相互影响。


BFCs是浮动元素的定位和清理非常重要 - 浮动元素只影响相同的BFC。当你< float 一个元素时,它将被从流中取出并通过floating重新插入。



查看以下示例:


  1. wrapper 将一个div浮动到左边,另一个浮动到右边。

  2. 浮动元素重新插入到BFC中,同时呈现未浮动元素。


  3. 因为您没有清除在BFC中浮动,所以 wrapper code> height将扩展到未浮动元素的大小。



    <覆盖> body {margin:0; } * {box-sizing:border-box; } .wrapper {border:1px solid; } .wrapper> * {display:inline-block;边框:1px纯红色;宽度:33.33%; height:100px; } .left {float:left; } .right {float:right; } .center {height:50px; }

     < div class =wrapper> < div class =left> Left< / div> < div class =center>中心< / div> < div class =right>右< / div> < / div>  

  4. clear 在BFC中浮动 - 现在高度将在包装器 BFC中正常运行。



    body {margin:0; } * {box-sizing:border-box; } .wrapper {border:1px solid; } .wrapper> * {display:inline-block;边框:1px纯红色;宽度:33.33%; height:100px; } .left {float:left; } .right {float:right; } .center {height:50px; } .wrapper:after {content:'';显示:块;明确:两者; }

     < div class =wrapper> < div class =left> Left< / div> < div class =center>中心< / div> < div class =right>右< / div> < / div>  




折叠边距


块的顶部和底部边距是有时将
合并(折合)成一个单一保证金,其大小是保证金中最大的保证金合并
,这种行为称为保证金折叠。


相邻块父母和第一个/最后一个孩子空白块的边距折叠。在此MDN文档中查看更多关于边距折叠的信息。



另请注意:


浮动和绝对定位元素的边距不会折叠。





那么这里真的发生了什么?


  1. 所以现在您已经了解了BFC以及第一种情况下的浮动容器的工作方式(当您没有指定边框时) - 这就是为什么 floatMe 不在其直接的 mainContent 包装中,正好为什么 wrapper mainContent 就像它看起来那样。


  2. 布局 IE 仅在IE7中使用,并且是非标准的。

  3. 其他所有发生的事情都是因为边距崩溃:

    a。 h2 pre 边距折叠(邻居兄弟姐妹

    b。 mainContent 向顶部移动一点以使用 body Parent和first /最后一个孩子



    c。作为 wrapper 取得 mainContent 的高度, wrapper height也向上移动。

    d。当你申请边界时会发生什么情况,上面(b)中的边界崩溃是无效的! (请参阅上面的MDN文档以了解原因)







希望事情现在看起来更好。干杯!

In order to understand what does a block formatting context do, I'm trying to find out what's going on when a BFC is not created.

I took the following demo from Everything you Know about Clearfix is Wrong:

.wrapper {
  width: 740px;
  background: #cccccc;
}
.leftSidebar {
  float: left;
  width: 200px;
}
.rightSidebar {
  float: right;
  width: 200px;
}
.mainContent {
  padding-right: 200px;
  padding-left: 200px;
}
.floatMe {
  float: left;
  background: teal;
  color: #fff;
}

<div class="wrapper">
  <div class="leftSidebar">
    <h2>Heading</h2>
    <pre>.leftSidebar {
  float:left;
  width:200px;
}</pre>
  </div>
  <div class="rightSidebar">
    <h2>Heading</h2>
    <pre>.rightSidebar {
  float:right;
  width:200px;
}</pre>
  </div>
  <div class="mainContent">
    <h2>Heading</h2>
    <pre>.mainContent {
  padding-right:200px;
  padding-left:200px;
}</pre>
    <div class="floatMe">
      <pre>.floatMe {
  float:left;
  background:teal;
  color:#fff;
}</pre>
    </div>
  </div>
</div>

According to that article(emphasis mine):

In modern browsers:

All elements belong to the same block formatting context so adjacent margins collapse. The heading’s margin "sticks out" of the wrapper to butt against the p. Unlike in IE, it is that margin (not the one on the black box) that creates the gap above the wrapper.

I cannot understand what does "the same block formatting context" refers to. I want to know why such a weird layout is produced without a block formatting context.

I've tried to figure out the exact layout by adding * {border: 1px solid blue;} to CSS, but the overall layout changed greatly after this change: now it behaves as if wrapper is a block formatting context!

.wrapper {
  width: 740px;
  background: #cccccc;
}
.leftSidebar {
  float: left;
  width: 200px;
}
.rightSidebar {
  float: right;
  width: 200px;
}
.mainContent {
  padding-right: 200px;
  padding-left: 200px;
}
.floatMe {
  float: left;
  background: teal;
  color: #fff;
}
* {
  border: 1px solid blue;
}

<div class="wrapper">
  <div class="leftSidebar">
    <h2>Heading</h2>
    <pre>.leftSidebar {
  float:left;
  width:200px;
}</pre>
  </div>
  <div class="rightSidebar">
    <h2>Heading</h2>
    <pre>.rightSidebar {
  float:right;
  width:200px;
}</pre>
  </div>
  <div class="mainContent">
    <h2>Heading</h2>
    <pre>.mainContent {
  padding-right:200px;
  padding-left:200px;
}</pre>
    <div class="floatMe">
      <pre>.floatMe {
  float:left;
  background:teal;
  color:#fff;
}</pre>
    </div>
  </div>
</div>

Please tell me what's going on.

解决方案

Good question, got me thinking a lot!

There are lot of concepts at play here, so I'll get to them one by one:

Buggy IE:

Whatever is mentioned in this old article about IE can be easily ignored if you do not have to design for IE7 or IE8 compatibility mode. This behavior is due to hasLayout property used internally by IE7.

See this MSDN doc for IE7:

What is "HasLayout" and why is it important?

There are several bugs in Internet Explorer that can be worked around by forcing "a layout" (an IE internal data structure) on an element.

Clearly this is a non-standard workaround and along with brings up a lot of inconsistencies. Read about this here too.


Block Formatting Context (BFC):

Excerpts from this MDN doc:

A block formatting context is a part of a visual CSS rendering of a Web page. It is the region in which the layout of block boxes occurs and in which floats interact with each other.

BFCs are very important for positioning and clearing of floated elements- floated elements affects only within the same BFCs. When you float an element, it is taken out of the flow and reinserted by "floating".

See the examples below:

  1. The inside of wrapper is a BFC where you float one div to left and another to the right.

  2. The floated elements are reinserted into the BFC while rendering around the element that is not floated.

  3. As you have not cleared the floating in the BFC, the wrapper height will extend to the size of the element that is not floated.

        body{
          margin: 0;
        }
        *{
          box-sizing: border-box;
        }
        .wrapper{
          border: 1px solid;
        }
        .wrapper > * {
          display: inline-block;
          border: 1px solid red;
          width: 33.33%;
          height: 100px;
        }
        .left{
          float: left;
        }
        .right{
          float: right;
        }
        .center{
          height: 50px;
        }

        <div class="wrapper">
          <div class="left">Left</div>
          <div class="center">Center</div>
          <div class="right">Right</div>
        </div>

  4. See what happens when you clear the floating in the BFC- now the heights will behave normally in the wrapper BFC.

        body{
          margin: 0;
        }
        *{
          box-sizing: border-box;
        }
        .wrapper{
          border: 1px solid;
        }
        .wrapper > * {
          display: inline-block;
          border: 1px solid red;
          width: 33.33%;
          height: 100px;
        }
        .left{
          float: left;
        }
        .right{
          float: right;
        }
        .center{
          height: 50px;
        }
        .wrapper:after{
          content: '';
          display: block;
          clear: both;
        }

        <div class="wrapper">
          <div class="left">Left</div>
          <div class="center">Center</div>
          <div class="right">Right</div>
        </div>


Collapsing Margins:

Top and bottom margins of blocks are sometimes combined (collapsed) into a single margin whose size is the largest of the margins combined into it, a behavior known as margin collapsing.

Margins collapse for adjacent blocks, parent and first/last child and empty blocks. See more about margin collapsing in this MDN doc.

Also note that:

Margins of floating and absolutely positioned elements never collapse.



So what really happens here?

  1. So now you will have understood about BFCs and also how floating containers work in first case (when you have no borders specified) - that's why floatMe stays out of its immediate mainContent wrapper and exactly why the height of wrapper and mainContent is as it looks there.

  2. Layout and IE referred to are only in IE7 and is non-standard.

  3. Everything else that happens is because of margin collapsing:

    a. h2 and pre margins collapse (adjacent siblings)

    b. mainContent shifts a little bit to the top to collapse with the margin on the body (Parent and first/last child)

    c. As wrapper takes the height of mainContent, the wrapper height is also shifted upwards.

    d. What happens when you apply borders is that the margin collapsing in (b) above is nullified! (see MDN doc above as to why)



Hope things are looking better now. Cheers!

这篇关于块格式化上下文,折叠边距和浮动容器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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