CSS块格式化上下文如何工作? [英] How does the CSS Block Formatting Context work?

查看:141
本文介绍了CSS块格式化上下文如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

CSS封锁格式上下文如何运作?



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



块盒和行内盒)布局在正常流程?



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



新的块格式化上下文仍然是块格式化,因此在绘制一个框时,它也会将浮动元素视为不退出。这是正确的还是我误解了新块格式化上下文?



更新:更多问题




但是它的主要用途是停止浮动,例如在主要内容div中,实际上清除浮动的侧栏,即在源代码中较早出现的浮点。


我不明白的意思,我会提供一个例子,也许你会明白我。



div class =snippetdata-lang =jsdata-hide =truedata-console =truedata-babel =false>

  .content {background:#eee;颜色#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 =内容> < h3>这是内容框< / h3> < p>它包含一个左浮动框,您可以看到实际内容div在浮动下,但它是& lt; h3& gt;和< p& < b>行框< / b>缩短以便为浮标腾出空间。这是正常的行为。< / p> < div class =float> floated box< / div>< / div>  

我认为浮动框应该浮动到控制块的顶部 - 类 content 的div。此外,如果浮动框出现在标记的早期,那么它将显示我认为应该是什么。



  .content {background:#eee;颜色#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 =float>浮动框< / div> < h3>这是内容框< / h3> < p>它包含一个左浮动框,您可以看到实际内容div在浮动下,但它是& lt; h3& gt;和< p& < b>行框< / b>这是正常的行为< / p>< / div>  



我们如何解释这个?我们可以使用块格式化上下文和内联格式化上下文来解释它吗?

解决方案

封锁格式上下文


浮动,绝对定位的
元素,块容器(例如
inline-blocks,table-cells和
table-caption)块
盒和带有'overflow'的块框
除了'visible'(除非
值已经传播到
视口)建立新块格式上下文

使用粗体,确定位是非常重要的。



这意味着你使用的元素 overflow (可见以外的任何东西)或 float inline-block ..等变得负责其子元素的布局。它是子元素,然后包含,无论是浮动或折叠边距,他们应该完全包含在它们的边界父。


在块格式化上下文中,每个
盒的左外边缘触及包含块的左
边for
从右到左的格式化,右边缘
touch)


意味着:



因为框只能是矩形而不是不规则形状,这意味着两个浮点之间(或者甚至在一个浮点之间)的新的块格式化上下文不会缠绕相邻的侧浮。内部的子盒子只能延伸到远离他们父母的左边(或在RTL右边)的边缘。这是对柱状样式布局有用的行为。然而,它的主要用途是停止浮动,例如在主要内容div,实际上清除浮动的侧栏,即在源代码中较早出现的浮动。






Float清除



在正常情况下,浮动广告应清除之前浮动在整个源代码中的所有以前浮动的元素,而不仅仅是您显示的column
float clear specs的告诉报价是:


此属性指示
元素的框可能不是与早先浮动框相邻的

'clear'属性不考虑
浮动在元素本身或在其他块格式化上下文


所以说,你有一个三列布局,左右列分别左右浮动,边栏现在在新的块格式化上下文中,因为它们是浮动的(记住float也是一个建立一个新的BFC的属性),所以你可以愉快地浮动列表元素在它们内,他们只清除浮动列,他们不再关心浮动以前在源代码中的侧面列。






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



你可以简单地从两侧边缘,使它看起来整齐地坐在两个侧面浮动列之间,并采取剩余的宽度,一种常见的方式获得所需的宽度,如果中心列是流体 - 这将是很好,直到你需要在您的内容div中使用浮动/清除(对于那些使用clearfix黑客或包含它们的模板的常见情况)



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



 #left-col {border: 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>左栏< / div>< div id =right-col>右栏< / div>< div id =content> < h3>主要内容< / h3> < p> Lorem ipsum etc ..< / p> < div class =floated>这是一个浮动框< / div> < div class =floated>此为浮动框< / div>< / div>  



它产生以下内容:





一般来说这很好,特别是如果你没有背景颜色或内部( c>的顶部边距和 c>的顶部边距),它们可能只是 code> p 的下边距实际上并不真正包含在内容div(lightgrey背景)。



因此,对于上述代码的同样简单的边际场景:

  .clear-r {clear:right;} 

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

 < div class =floated clear-r>这是一个浮动的清除框< / 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>左栏< / div>< div id =right-col>右栏< / div>< div id =content> < h3>主要内容< / h3> < p> Lorem ipsum etc ..< / p> < div class =floated>这是一个浮动框< / div> < div class =floated clear-r> this a floated cleared box< / div>< / div>  

/ p>

这次你得到这个:





第二个浮点正在清除右侧,但它清除右侧列的整个高度。正确的列在源代码中较早浮动,因此它被清除了!也许注意, h3 p 边距仍然折叠(不包含)。 p>




为了儿童的缘故,建立一个块格式化上下文!



并最终使主内容列负责 - 成为块格式化上下文 - 其内容:remove margin:0 200px; 从主要内容CSS和 ADD overflow:hidden; ,您会得到:



 #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>左栏< / div>< div id =right-col>右栏< / div>< div id =content> < h3>主要内容< / h3> < p> Lorem ipsum etc ..< / p> < div class =floated>这是一个浮动框< / div> < div class =floated clear-r> this a floated cleared box< / div>< / div>  

/ p>

>



这可能更像是你期望发生的事情,注意浮动包含,他们清除正确忽略右边列,还有 h3 p 页边距而不是折叠。



边缘不太明显(IE仍然不能得到它们相当正确),然而刚刚发生在中心主要内容是,它成为一个块格式化上下文,现在负责自己的子(后代)元素。它实际上非常类似于微软的早期概念的hasLayout,它使用相同的属性 display:inline-block float ,和 overflow 除了visible以外的任何东西,当然表单元格总是有布局..但它没有错误);



希望有帮助,任何问题都可以随时问!






更新: :



当你说但当用户代理绘制框时忽略浮动元素,当他们填写内容时考虑它们。



是浮子通常覆盖在他们的容器盒,你的意思是关于父边界吗?当一个块元素被绘制并且它包含一个浮动块时,块本身在浮动下被绘制为一个矩形,并且它是其他子元素的内联匿名框或简单的线框,被缩短以腾出空间



使用以下代码:



  #content {background:#eee;颜色#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 =内容> < div class =float>浮动框< / div> < h3>这是内容框< / h3> < p>它包含一个左浮动框,您可以看到实际内容div在浮动下,但它是& lt; h3& gt;和< p& < b>行框< / b>这是正常的行为< / p>< / div>  



这产生了这个:





你看到父元素实际上不包含float,因为它不会完全包装它。float只是浮动顶部的内容 - 如果你要继续添加内容到div,它最终将包裹在浮动下面,因为没有必要的(匿名)行框 p 元素来缩短自己。



我已经为段落元素着色了,所以你可以看到它也实际上在浮动下,黑灰色背景是段落开始的地方,白色文本是匿名线框开始 - 这只是实际上是那些让房间的浮动,除非你说,否则(即你改变上下文)



上面的图片,如果你在边距左侧的 p 元素,是的,它会停止文本包裹在浮动的底部,因为行框白色文本)将只触及其容器的左边缘,并且您将带有 p 的彩色背景到右侧,清除浮动,但是你赢了' t改变了 p 的格式化上下文的行为。像上面第一个图片中的中心列;)


How does the CSS Block Formatting Context work?

CSS2.1 specifications says that in a block formatting context, boxes are laid out vertically, starting at the top. This happens even if there are floated elements in the way, except if the block box established a new block formatting context. As we know, when browsers render block boxes in a block formatting context, the floated element is omitted, why does establishing a new block formatting context work?

How are boxes (block boxes and inline boxes) laid out in the normal flow?

I read somewhere that block elements generate block boxes, but floating elements are ignored when a user agent draws box and take them into account when they fill out content. Whilst floating elements will overlap other elements's boundary of the boxes, the solution is establishing a new block formatting context for the overlapped elements using overflow:hidden.

"New block formatting context is still block formatting", so when drawing a box, it will also treat the floating element as if it doesn't exit. Is that right or have I misunderstood "new block formatting context?"

Update:more questions

By saying "It's this behaviour that's useful for columnar style layouts. The main use of it however is to stop floats, say in a "main content" div, actually clearing floated side columns, i.e. floats that appear earlier in the source code."

I don't understand the meaning, I will provide an example, maybe you will understand me.

.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>

I thought the floating box should float to the top of the containg block-the div with class content. Besides, if the floating box appears earlier in the markup, then it will display what I think it should be.

.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>

How can we explain this? Can we use "block formatting context and inline formatting context" to explain it?

解决方案

Block Formatting Contexts

Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.

With my bold, it's the establish bit that is important

What this means is that the element you use overflow (anything other than visible) or float or inline-block..etc on becomes responsible for the layout of its child elements. It's the child elements which are then "contained", whether that's floats or collapsing margins they should be wholly contained by their bounding parent.

In a block formatting context, each box's left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch)

What the above line means:

Because a box can only be rectangular and not irregular shaped this means a new block formatting context between two floats (or even beside one) will not wrap around neighbouring side floats. The inner, child boxes can only extend as far as to touch their parents left (or right in RTL) edge. It's this behaviour that's useful for columnar style layouts. The main use of it however is to stop floats, say in a "main content" div, actually clearing floated side columns, i.e. floats that appear earlier in the source code.


Float Clearance

In normal circumstances floats are supposed to clear all previous floated elements, that's previously floated in the whole source code, not just your displayed "column" The telling quote from the "float clearance specs" is:

This property indicates which sides of an element's box(es) may not be adjacent to an earlier floating box. The 'clear' property does not consider floats inside the element itself or in other block formatting contexts

So say you have a three column layout where the left and right columns are floated left and right respectively, the side columns are now in new Block Formatting Contexts, because they are floated (remember float is also one of the properties that establish a new BFC), so you can happily float list elements inside them and they only clear floats which are already inside the side columns they no longer care about floats previously in the source code


To make the main content a new Block Formatting Context or not?

Now that middle column, you can simply margin it from both sides so that it appears to sit neatly between the two side floated columns and take the remaining width, a common way to get desired width if the centre column is "fluid" - which will be fine until you need to use floats/clearance inside your content div (a common occurrence for those using "clearfix" hacks or templates including them)

Take this very simple code:

#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>

It produces the following:

In general this is fine, especially if you have no background colours or internal (in the main content) floats - notice the floats are fine (not cleared yet) they're doing probably what you except them to but they, the H3's top margin and the p's bottom margin are not actually really contained by the content div (lightgrey background).

So to the same simple margined scenario of above code add:

.clear-r {clear: right;}

to the CSS, and change the second HTML floated box to:

<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>

This time you get this:

The second float is clearing the right side but it's clearing the whole height of the right column. The right column is floated earlier in the source code so it's clearing it as told! Probably not the desired effect though, also note the h3 and p margins are still collapsed (not contained).


Make it establish a Block Formatting Context, for the sake of the children!

and finally make the main content column take responsibility - become a Block Formatting Context - for its contents : remove margin: 0 200px; from the main content CSS and ADD overflow: hidden; and you get this:

#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>

This is probably much more like what you would expect to happen, note now the floats are contained, they clear properly ignoring the right side column, and also the h3 and p margins are contained instead of collapsed.

With the extensive use of resets these days the margins are less noticeable (and IE still doesn't get them quite right) however what just happened to the centre "main content" is that it became a Block Formatting Context and is now responsible for its own child (descendant) elements. It's actually very similar to Microsoft's early days notion of hasLayout, it uses the same properties display: inline-block, float, and overflow anything other than visible, and of course table cells always have layout.. it is however without the bugs ;)

Hope that helps a bit, any questions feel free to ask!


Update: re more information in question:

When you say "but floating elements are ignored when user agent draws box and take them into account when they fill out content."

Yes floats normally overlay their container boxes, is that what you mean about parent boundaries? When a block element is drawn and it contains a float the block parent itself is drawn as a rectangle under the float and it is the "inline anonymous boxes" or simply "line boxes" of the other child elements that are shortened to make room for the float

Take this code:

#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>

Which produces this:

You see that the parent element doesn't actually contain the float, as in it doesn't wrap it entirely.. the float is simply floating on top of the content - if you were to keep adding content to the div it would eventually wrap underneath the float because there would be no need for the (anonymous) "line boxes" of the p element to shorten themselves any more.

I've coloured the paragraph element so you can see that it too actually goes under the float, the darkgray background is where the paragraph starts, the white text is where the "anonymous line box" starts - it's only actually them that "make room" for the float, unless you tell it otherwise (i.e. you change the context)

Again referring to the above picture, if you were to margin the left side of thep element, yes it will stop the text wrapping under the bottom of the float because the "line boxes" (the white text) will only touch the left edge of their container, and you will bring the coloured background of the p to the right, clear of the float, but you won't have changed the behaviour of the p's formatting context. Like the centre column in the first picture way above ;)

这篇关于CSS块格式化上下文如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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