【问题标题】:How does the CSS Block Formatting Context work?CSS 块格式化上下文是如何工作的?
【发布时间】:2011-09-06 00:08:25
【问题描述】:

CSS Block Formatting Context 是如何工作的?

CSS2.1 规范规定,在块格式化上下文中,框从顶部开始垂直布局。即使有浮动元素,也会发生这种情况,除非块框建立了新的块格式化上下文。众所周知,当浏览器在块格式化上下文中渲染块框时,浮动元素被省略了,为什么建立一个新的块格式化上下文会起作用?

框(块框和内联框)在正常流程中是如何布局的?

我在某处读到块元素会生成块框,但是当用户代理绘制框时会忽略浮动元素,并在填充内容时将其考虑在内。虽然浮动元素会与框的其他元素的边界重叠,但解决方案是使用 overflow:hidden 为重叠元素建立新的块格式化上下文。

“新的块格式化上下文仍然是块格式化”,所以在绘制一个框的时候,它也会把浮动元素当作不退出一样对待。这是对的还是我误解了“新的块格式化上下文”?

更新:更多问题

通过说“这种行为对柱状样式布局很有用。然而,它的主要用途是停止浮动,比如在“主要内容”div中,实际上清除浮动的侧列,即在源中较早出现的浮动代码。”

我不明白意思,我举个例子,也许你会明白。

.content {
  background: #eee;
  color #000;
  border: 3px solid #444;
  width: 500px;
  height: 200px;
}
.float {
  background: rgba(0, 0, 255, 0.5);
  border: 1px solid #00f;
  width: 150px;
  height: 150px;
  float: right;
}
p {
  background: #444;
  color: #fff;
}
<div class="content">
  <h3>This is a content box</h3>
  <p>It contains a left floated box, you can see the actual content div does go under the float, but that it is the &lt;h3&gt; and &lt;p&gt; <b>line boxes</b> that are shortened to make room for the float. This is normal behaviour.</p>
  <div class="float">floated box</div>
</div>

我认为浮动框应该浮动到包含块的顶部 - 类为 content 的 div。此外,如果浮动框出现在标记的前面,那么它会显示我认为应该是的。

.content {
  background: #eee;
  color #000;
  border: 3px solid #444;
  width: 500px;
  height: 200px;
}
.float {
  background: rgba(0, 0, 255, 0.5);
  border: 1px solid #00f;
  width: 150px;
  height: 150px;
  float: right;
}
p {
  background: #444;
  color: #fff;
}
<div class="content">
  <div class="float">floated box</div>
  <h3>This is a content box</h3>
  <p>it contains a left floated box, you can see the actual content div does go under the float, but that it is the &lt;h3&gt; and &lt;p&gt; <b>line boxes</b> that are shortened to make room for the float, this is normal behaviour</p>
</div>

我们该如何解释呢?可以用“块格式化上下文和内联格式化上下文”来解释吗?

【问题讨论】:

标签: css


【解决方案1】:

Block Formatting Contexts

浮动,绝对定位 元素,块容器(例如 内联块、表格单元和 表标题)不是块 框和带有“溢出”的块框 除了“可见”(除非那个 值已传播到 viewport) 为其内容建立新的块格式化上下文

用我的粗体字,重要的是 建立

这意味着您使用的元素 overflow(除可见之外的任何内容)或 floatinline-block..etc 将负责其子元素的布局。然后是“包含”的子元素,无论是浮动还是折叠边距,它们都应该完全由其边界父元素包含。

在块格式化上下文中,每个 盒子的左外边缘接触左边 包含块的边缘(对于 从右到左格式,右边缘 触摸)

以上行的含义:

因为一个盒子只能是矩形而不是不规则形状,这意味着两个浮动(甚至在一个旁边)之间的新块格式化上下文不会环绕相邻的侧浮动。内部的子框只能延伸到接触其父级的左(或 RTL 中的右)边缘。正是这种行为对柱状样式布局很有用。然而,它的主要用途是停止浮动,比如在“主要内容”div 中,实际上清除浮动侧列,即源代码中较早出现的浮动。


Float Clearance

在正常情况下,浮动应该清除所有先前浮动的元素,这些元素以前浮动在整个源代码中,而不仅仅是您显示的“列” “浮动间隙规格”中的引语是:

这个属性表示哪边 一个元素的盒子可能不是 与较早的浮动框相邻。 'clear' 属性不考虑 浮动在元素本身内部或在其他块格式化上下文中

假设您有一个三列布局,其中左列和右列分别向左和向右浮动,侧列现在位于新的块格式化上下文中,因为它们是浮动的(请记住,浮动也是建立的属性之一一个新的 BFC),因此您可以愉快地在其中浮动列表元素,并且它们只清除已经在侧列内的浮动,它们不再关心以前在源代码中的浮动


是否使主要内容成为新的块格式上下文?

现在中间的列,您可以简单地从两侧设置边缘,使其看起来整齐地位于两侧浮动列之间并占据剩余宽度,如果中间列是“流体”,这是获得所需宽度的常用方法- 在您需要在内容 div 中使用浮动/清除(对于使用“clearfix”黑客或包含它们的模板的人来说,这很常见)

使用这个非常简单的代码:

#left-col {
  border: 1px solid #000;
  width: 180px;
  float: left;
}
#right-col {
  border: 1px solid #000;
  width: 180px;
  float: right;
  height: 200px;
}
#content {
  background: #eee;
  margin: 0 200px;
}
.floated {
  float: right;
  width: 180px;
  height: 100px;
  background: #dad;
}
<div id="left-col">left column</div>
<div id="right-col">right column</div>

<div id="content">
  <h3>Main Content</h3>
  <p>Lorem ipsum etc..</p>
  <div class="floated">this a floated box</div>
  <div class="floated">this a floated box</div>
</div>

它产生以下内容:

一般来说这很好,特别是如果您没有背景颜色或内部(在主要内容中)浮动 - 请注意浮动很好(尚未清除)他们可能正在做你除了他们之外的事情 但是 它们,H3 的上边距和p 的下边距实际上并没有真正包含在内容 div(浅灰色背景)中。

所以在上面代码的同样简单的边距场景中添加:

.clear-r {clear: right;}

到 CSS,并将第二个 HTML 浮动框更改为:

<div class="floated clear-r"> this a floated cleared box</div>

#left-col {
  border: 1px solid #000;
  width: 180px;
  float: left;
}
#right-col {
  border: 1px solid #000;
  width: 180px;
  float: right;
  height: 200px;
}
#content {
  background: #eee;
  margin: 0 200px;
}
.floated {
  float: right;
  width: 180px;
  height: 100px;
  background: #dad;
}
.clear-r {
  clear: right;
}
<div id="left-col">left column</div>
<div id="right-col">right column</div>

<div id="content">
  <h3>Main Content</h3>
  <p>Lorem ipsum etc..</p>
  <div class="floated">this a floated box</div>
  <div class="floated clear-r">this a floated cleared box</div>
</div>

这次你得到了这个:

第二个浮点数正在清除右侧,但它正在清除右列的整个高度。右列在源代码中较早地浮动,因此它按照说明清除它!不过可能不是预期的效果,还要注意h3p 边距仍然折叠(不包含)。


为了孩子们,让它建立一个块格式化上下文!

最后让主要内容列负责 - 成为块格式上下文 - 对其内容:从主要内容 CSS 中删除 margin: 0 200px;添加 @987654341 @ 你得到这个:

#left-col {
  border: 1px solid #000;
  width: 180px;
  float: left;
}
#right-col {
  border: 1px solid #000;
  width: 180px;
  float: right;
  height: 200px;
}
#content {
  background: #eee;
  overflow: hidden;
}
.floated {
  float: right;
  width: 180px;
  height: 100px;
  background: #dad;
}
.clear-r {
  clear: right;
}
<div id="left-col">left column</div>
<div id="right-col">right column</div>

<div id="content">
  <h3>Main Content</h3>
  <p>Lorem ipsum etc..</p>
  <div class="floated">this a floated box</div>
  <div class="floated clear-r">this a floated cleared box</div>
</div>

这可能更像您期望发生的那样,注意现在浮动已包含,它们会正确清除而忽略右侧列,并且 h3p 边距被包含而不是折叠。

如今,随着重置的广泛使用,边距不那么明显了(IE 仍然不能完全正确),但是中心“主要内容”刚刚发生的事情是它变成了块格式化上下文,现在是负责自己的子(后代)元素。它实际上与微软早期的 hasLayout 概念非常相似,它使用相同的属性display: inline-blockfloatoverflow,除了可见之外的任何东西,当然表格单元格总是有布局.. 但是没有错误;)

希望对你有所帮助,有问题欢迎提问!


更新:有关问题的更多信息:

当您说“但是当用户代理绘制框时会忽略浮动元素并在填写内容时将它们考虑在内。”

是的,浮动通常会覆盖它们的容器框,这就是您对父边界的意思吗?当一个块元素被绘制并且它包含一个浮点数时,块父元素本身被绘制为浮点数下方的一个矩形,并且它是其他子元素的“内联匿名框”或简称为“行框”,它们被缩短以腾出空间浮动

获取此代码:

#content {
  background: #eee;
  color #000;
  border: 3px solid #444;
}
.float {
  background: rgba(0, 0, 255, 0.5);
  border: 1px solid #00f;
  width: 150px;
  height: 150px;
  float: left;
  margin: 10px;
}
p {
  background: #444;
  color: #fff;
}
<div id="content">
  <div class="float">floated box</div>
  <h3>This is a content box</h3>
  <p>it contains a left floated box, you can see the actual content div does go under the float, but that it is the &lt;h3&gt; and &lt;p&gt; <b>line boxes</b> that are shortened to make room for the float, this is normal behaviour</p>
</div>

产生这个:

你看到父元素实际上并不包含浮动,因为它没有完全包裹它。浮动只是 浮动 在内容之上 - 如果你要继续向 div 添加内容,它最终会包裹在浮动下方,因为p 元素的(匿名)“行框”不再需要缩短自身。

我已经为段落元素着色,因此您可以看到它实际上也在浮动下方,深灰色背景是段落开始的地方,白色文本是“匿名行框”开始的地方 - 实际上只有它们为浮动“腾出空间”,除非您另有说明(即您更改上下文)

再次参考上图,如果您要在p 元素的左侧添加边距,是的,它会停止文本在浮动底部下方的换行,因为“行框”(白色文本)会仅触摸其容器的左边缘,您会将p 的彩色背景移至右侧,清除浮动,但您不会更改p 的格式化上下文的行为。就像上面第一张图片中的中心栏一样;)

【讨论】:

  • clairesuzy,非常感谢!这对我帮助很大。但我还有一些问题。我已将其添加到原始问题中。希望您能帮助我。
  • @eileen 发生了两件事-我认为第一个示例解释了您的额外问题。紫色浮动框出现在内容之后,因为那是它们在源中的位置,浮动不会浮动到顶部,超过之前的内容(因为它的上边距不能高于它应该在的位置) - 左列和右列也是浮动框,它们在源中较早并且中间列不会成为新的 BFC,如果您尝试清除紫色浮动,它们也会清除较早的源端浮动列..这有帮助吗?
  • @eileen 该链接描述了块级元素和内联级元素,只是在格式化上下文中的基础知识。块元素将始终占用 100% 的宽度并彼此叠放(默认情况下)- 内联元素并排放置,如链接、跨度等。它们甚至不占用宽度或高度,因此他们别无选择。浮动元素自动成为块级元素,因此如果您浮动内联级&lt;span&gt;,它就会变成块级&lt;div&gt;
  • cont.. p 的背景位于浮动下方的原因是浮动元素已从流中移除,因为相邻元素真的不知道它们在那里,并且因为它们属于相同的格式化上下文,p 会查看它的父容器的尺寸..(这就是为什么你不能把 100% 宽的东西放在浮动旁边 - 因为对它来说 100% 是 100%容器。只有匿名框最终确定浮动存在;)
  • @clairesuzy - 您发布的图片已发布,您可以重新发布吗?
猜你喜欢
  • 1970-01-01
  • 2016-05-08
  • 2021-07-03
  • 2011-01-14
  • 2019-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多