margin折叠及hasLayout && Block Formatting Contexts
margin折叠的产生有几个条件:
- 这些margin都处于普通流中,并在同一个BFC中;
- 这些margin没有被非空内容、padding、border 或 clear 分隔开;
- 这些margin在垂直方向上是毗邻的,包括以下几种情况:
1、一个box的top margin与第一个子box的top margin
2、一个box的bottom margin与最后一个子box的bottom margin,但须在该box的height 为auto的情况下
3、一个box的bottom margin与紧接着的下一个box的top margin
4、一个box的top margin与其自身的bottom margin,但须满足没创建BFC、零min-height、零或者“auto”的height、没有普通流的子box
垂直方向上毗邻的box不会发生折叠的情况:
- 根元素的外边距不会参与折叠
- 一个有clearance的box的上下margin毗邻,它会与紧接着的下一个box发生margin折叠,但折叠后的margin不会再与它们父box的bottom margin折叠
折叠边距的计算
当两个margin都是正值的时候,取两者的最大值;当 margin 都是负值的时候,取的是其中绝对值较大的,然后,从 0 位置,负向位移;当有正有负的时候,先取出负 margin 中绝对值中最大的,然后,和正 margin 值中最大的 margin 相加。但必须注意,所有毗邻的margin要一起参与运算,不能分步进行。
以下内容转载自:http://www.smallni.com/haslayout-block-formatting-contexts/
1.hasLayout
‘Layout’ 是 IE 的专有概念,它决定了元素如何对其内容进行定位和尺寸计算,与其他元素的关系和相互作用,以及对应用还有使用者的影响。
- 概念说明:
- ‘Layout’ 可以被某些 CSS property(特性)不可逆的触发,而某些 HTML 元素本身就具有 layout 。
- ‘Layout’ 在 IE 中可以通过 hasLayout 属性来判断一个元素是否拥有 layout ,如 object.currentStyle.hasLayout 。
- ‘Layout’ 是 IE 浏览器渲染引擎的一个内部组成部分。在 IE 浏览器中,一个元素要么自己对自身的内容进行组织和计算大小, 要么依赖于包含块来计算尺寸和组织内容。为了协调这两种方式的矛盾,渲染引擎采用了 ‘hasLayout’ 属性,属性值可以为 true 或 false。 当一个元素的 ‘hasLayout’ 属性值为 true 时,我们说这个元素拥有了一个布局(layout),即成功触发hasLayout
- 触发方式:
- 默认拥有布局的元素:
1234567
<
html
>, <
body
>
<
table
>, <
tr
>, <
th
>, <
td
>
<
img
>
<
hr
>
<
input
>, <
button
>, <
select
>, <
textarea
>, <
fieldset
>, <
legend
>
<
iframe
>, <
embed
>, <
object
>, <
applet
>
<
marquee
>
- 可触发 hasLayout 的 CSS 特性:
1234567
display
: inline-
block
/*ALL*/
height
: (除
auto
外任何值)
/*仅适用IE6 7*/
width
: (除
auto
外任何值)
/*仅适用IE6 7*/
float
: (
left
或
right
)
/*ALL*/
position
:
absolute
/*ALL*/
writing-mode: tb-rl
/*ALL*/
zoom: (除
normal
外任意值)
/*仅适用IE6 7*/
- IE7 还有一些额外的属性(不完全列表)可以触发 hasLayout :
12345678
min-height
: (任意值)
/*以下适用IE7+*/
min-width
: (任意值)
max-height
: (除
none
外任意值)
max-width
: (除
none
外任意值)
overflow
: (除
visible
外任意值,仅用于块级元素)
overflow-x: (除
visible
外任意值,仅用于块级元素)
overflow-y: (除
visible
外任意值,仅用于块级元素)
position
:
fixed
- IE6 以前的版本(也包括 IE6 及以后所有版本的混杂模式,其实这种混杂模式在渲染方面就相当于 IE 5.5), 通过设置任何元素的 ‘width’ 或 ‘height’(非auto)都可以触发 hasLayout ; 但在 IE6 和 IE7 的标准模式中的行内元素上却不行,设置 ‘display:inline-block’ 才可以。
- 默认拥有布局的元素:
2.Block Formatting Contexts(BFC)
IE有它自己的hasLayout属性,那么非IE浏览器呢?非IE浏览器采用的就是BFC(块格式化上下文)
- 概念说明:
- BFC是 W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。是页面 CSS 视觉渲染的一部分,用于决定块盒子的布局及浮动相互影响范围的一个区域。
- 在创建了 BFC的元素中,其子元素会一个接一个地放置。垂直方向上他们的起点是一个包含块的顶部,两个相邻的元素之间的垂直距离取决于 ‘margin’ 特性。在BFC中相邻的块级元素的垂直边距会折叠(collapse)。
- 在BFC 中,每一个元素左外边与包含块的左边相接触(对于从右到左的格式化,右外边接触右边), 即使存在浮动也是如此(尽管一个元素的内容区域会由于浮动而压缩),除非这个元素也创建了一个新的BFC。
- 在CSS3中,对这个概念做了改动:http://www.w3.org/TR/css3-box/#block-level0CSS3中,将BFC 叫做 flow root。
- 触发方式
1234
float
:(任何值除了
none
)
overflow
:(任何值除了
visible
)
display
:(
table-cell
/
table-caption
/inline-
block
)
position
:(任何值除了
static
/
relative
)
Tips:我们有时会用overflow:hidden的方法去清除浮动,就是因为触发了元素的块格式化上下文(IE6 7要申明zoom为1),这个方法的确简单,但很暴力 – -#
3. hasLayout 和 BFC 的特点
3.1 在触发 hasLayout 的元素和创建了 BFC的元素中,浮动元素参与高度的计算
情况1:没有创建 BFC的块级非替换元素,触发了 IE 的 hasLayout。
分析以下代码:
1
2
3
4
5
6
7
|
< div style = "width:300px;" > < div id = "Container" style = "background:silver; zoom:1;" > < span id = "SPAN1" style = "background:gray;" >simple text</ span > < div id = "DIV1" style = "width:150px; height:50px; background:dimgray;" >in flow</ div > < div id = "DIV2" style = "float:left; background:gold;" >float:left</ div > </ div > </ div > |
- Container 没有创建 block formatting context。
- Container 的 ‘zoom:1’设置,是为了触发 IE 中的 hasLayout;
- Container 的高度值为 auto,并且 ‘overflow’ 的值为默认的 ‘visible’;
- SPAN1 是一个行内元素, DIV1 是一个处于普通流中的块元素;
- DIV2 是一个浮动的块级元素。
根据 CSS2.1 规范第 10.6.3 部分的高度计算规则,在进行普通流中的块级非替换元素的高度计算时,浮动子元素不参与计算。
所以,在进行 Container 高度计算时,只受 SPAN1 和 DIV1 的影响,应该是它们两个的高度之和,所以最终银色部分不应该包含金色的部分。
这段代码在不同的浏览器环境中表现如下:
IE6 IE7 IE8(Q) | IE8(S) Firefox Chrome Safari Opera |
---|---|
去掉 Container 的 ‘zoom:1’ 后,各浏览器表现一致:
可见,IE 浏览器中,触发 hasLayout 的元素在进行高度计算的时候,其浮动的子元素也会参与运算。
情况2:创建了 BFC的块级非替换元素,未触发 IE 的 hasLayout。
分析以下代码:
1
2
3
4
5
6
7
|
< div style = "width:300px;" > < div id = "Container" style = "background:silver; overflow:hidden;" > < span id = "SPAN1" style = "background:gray;" >simple text</ span > < div id = "DIV1" style = "width:150px; height:50px; background:dimgray;" >in flow</ div > < div id = "DIV2" style = "float:left; background:gold;" >float:left</ div > </ div > </ div > |
- Container 的 ‘overflow:hidden;’ 创建了BFC;
- Container 的 ‘overflow:hidden;’,在 IE6 中未触发 hasLayout,但在 IE7(S) 中触发了 hasLayout;
- Container 的高度值为 ‘auto’;
- SPAN1 是一个行内元素,DIV1 是一个处于普通流中的块元素;
- DIV2 是一个浮动的块级元素。
根据 CSS2.1 规范第10.6.7部分的高度计算规则,在计算生成了 BFC的元素的高度时,其浮动子元素应该参与计算。
所以,在进行 Container 高度计算时,DIV2 也应该参与计算,所以最终银色部分应该包含金色的部分。
这段代码在不同的浏览器环境中表现如下:( 注意 IE7(S) 此时触发了 hasLayout )
IE6 IE7(Q) IE8(Q) | IE7(S) IE8(S) Firefox Chrome Safari Opera |
---|---|
可见,只要 Container 创建了 BFC,其浮动子元素就会参与其高度计算(IE7(S) 是由于 hasLayout 导致与其他浏览器的效果相同)。
3.2 与浮动元素相邻的、触发了 hasLayout 的元素或创建了 BFC 的元素,都不能与浮动元素相互覆盖
如果浮动元素的两侧有足够的空间放置该元素,则元素会紧邻浮动元素放置,必要时,该元素的宽度将会被压缩。否则它们可 能会定位到浮动元素的下方。
情况1:没有创建 BFC 的块级非替换元素,触发了 IE 的 hasLayout。
分析以下代码:
1
2
3
4
5
6
7
8
|
< div id = "Container" style="border:2px solid gold; width:300px; height:150px;<strong> background:url("grid2a.png") repeat;</ strong >"> < div id = "DIV1" style = " width:100px; height:100px; float:left; filter:alpha(opacity=50); opacity: 0.5;" > Float Block </ div > < div id = "DIV2" style = " zoom:1;" > If I had a single flower for every time I think about you, I could walk forever in my garden. </ div > </ div > |
- DIV1 是一个浮动元素,背景是 50% 的透明
- DIV2 的 ‘zoom:1’ 触发了 IE 中的 hasLayout。
其中,grid2a.png 背景是 100px * 100px 的图片:
根据 CSS 2.1 9.5 Floats 中的描述,浮动元素会覆盖普通流中的块容器。所以,DIV2 应该有一部分呢被 DIV1 覆盖。
这段代码在不同的浏览器环境中表现如下:(忽略 IE 中 3px BUG 的影响)
IE6 IE7 IE8(Q) | IE8(S) Firefox Chrome Safari Opera |
---|---|
情况2:创建了 BFC的块级非替换元素,未触发 IE 的 hasLayout。
分析以下代码:
1
2
3
4
5
6
7
8
|
< div id = "Container" style="border:2px solid gold; width:300px; height:150px;<strong> background:url("grid2a.png") repeat;</ strong >"> < div id = "DIV1" style = " width:100px; height:100px; float:left; filter:alpha(opacity=50); opacity: 0.5;" > Float Block </ div > < div id = "DIV2" style = " overflow:hidden;" > If I had a single flower for every time I think about you, I could walk forever in my garden. </ div > </ div > |
- DIV1 是一个浮动元素,背景是50%的透明
- DIV2 的 ‘overflow:hidden;’ 在 IE6 中未触发 hasLayout,但在 IE7(S) 中触发了 hasLayout。
根据 CSS 2.1 9.5 Floats 中的描述,创建了BFC的元素不能与浮动元素重叠, 所以,DIV2 应该有一部分被 DIV1 覆盖。
这段代码在不同的浏览器环境中表现如下:( 注意 IE7(S) 此时触发了 hasLayout )
IE6 IE7(Q) IE8(Q) | IE7(S) IE8(S) Firefox Chrome Safari Opera |
---|---|
3.3 触发 hasLayout 的元素和创建了 BFC的元素不会与它们的子元素发生外边距折叠
情况1:没有生成BFC的块级非替换元素,触发了 IE 的 hasLayout。
分析以下代码:
1
2
3
4
5
|
< div id = "Container" style = "width:300px; border:1px solid gold;" > < div id = "DIV1" style = "zoom:1; background:darkgray;" > < div id = "DIV2" style = "margin:30px 0; width:60px;" >content</ div > </ div > </ div > |
- Container 是宽度为300px,含有 border 的块元素,根据标准,它不会与子元素的 margin 发生空白边折叠。
- DIV1 的宽度没有设置,所以宽度等于 Container 的宽度。
- DIV1 的高度也没有设置,所以其高度取决于其内容的高度。
- DIV1 设置了 ‘zoom:1’,在 IE 中触发了 hasLayout。
根据 CSS 2.1 8.3.1 Collapsing margins 第一条,两个相邻的普通流中的块框在垂直位置的空白边会发生折叠现象。
DIV1 和 DIV2 应该发生空白边折叠,深灰色的 DIV1 应该刚好包含 ‘content’ 文本。
这段代码在不同的浏览器环境中表现如下:
IE6 IE7 IE8(Q) | IE8(S) Firefox Chrome Safari Opera |
---|---|
可见,在 IE 中,触发 hasLayout 的元素,阻止了它自身与子元素间的空白边折叠。
情况2:生成 BFC的块级非替换元素,未触发 IE 的 hasLayout。
分析以下代码:
1
2
3
4
5
|
< div id = "Container" style = "width:300px; border:1px solid gold;" > < div id = "DIV1" style = "overflow:hidden; background:darkgray;" > < div id = "DIV2" style = "margin:30px 0; width:60px;" >content</ div > </ div > </ div > |
- Container 是宽度为300px,含有 border 的块元素,根据标准,它不会与子元素的 margin 发生空白边折叠。
- DIV1 的宽度没有设置,所以宽度等于 Container 的宽度。
- DIV1 的高度也没有设置,所以其高度取决于其内容的高度。
- DIV1 设置了 ‘overflow:hidden’,在 IE6 中未触发 hasLayout,但在 IE7(S) 中触发了 hasLayout。
根据 CSS 2.1 8.3.1 Collapsing margins 第三条,生成BFC 的元素不会和在流中的子元素发生空白边折叠。
DIV1 和 DIV2 不应该发生空白边折叠,深灰色的 DIV1 应该撑满 Container 。
这段代码在不同的浏览器环境中表现如下:( 注意IE7(S) 此时触发了 hasLayout )
IE6 IE7(Q) IE8(Q) | IE7(S) IE8(S) Firefox Chrome Safari Opera |
---|---|
可见,在 IE 中,创建了 BFC,未触发 hasLayout 的元素,它自身与子元素间的空白边折叠还是会发生。
hasLayout 和 BFC 的异同及可能产生的问题
- 区别
- 在 IE8(S) 之前的版本中,没有规范中提及的 block formatting context 和 Inline formatting context 概念,而是用 hasLayout 来达到相似的目的。
- 在 IE 中可通过设置 ‘width’、’height’、’min-width’、’min-height’、’max-width’、’max-height’、 ‘zoom’、’writing-mode’ 来触发 hasLayout,而这些特性值的设置不能够使元素创建 BFC。
- 在 IE 中很多元素默认就是拥有布局的,如 IPUNT, BUTTON, SELECT, TEXTAREA 等,但是这些元素在标准中会形成 Inline formatting context (本博客后面会介绍)。
- 共同点
- 两者都是决定了对内容如何定位及大小计算的规则。
- 两者都决定了与其他元素的相互作用的规则。
- ‘table-cell’ 和 ‘table-caption’ 既是 hasLayout 的元素,又是可以创建 BFC 的元素。
- 浮动元素,绝对定位元素,inline-block 元素以及除 ‘visible’ 外任意值的 overflow(IE7) 在 IE 中可以触发 hasLayout,同时在标准中,又可以创建BFC。
- 可能产生的兼容性问题:
- 由于 hasLayout 和 BFC是对一类事物的不同理解,并且他们的启用条件不尽相同,因此如果一个元素设计时,在 IE 早期版本中触发了 hasLayout ,但在其他浏览器中又没有创建BFC,或者相反,一个元素在 IE 早期版本中没有触发 hasLayout ,在其他浏览器中却创建了 BFC(如设置了 ‘overflow:hidden’ ),将导致页面布局的重大差异。
解决方案
仅当一个元素即在 IE 早期版本中触发了 hasLayout,又在其他浏览器中创建了BFC时,才能避免上述问题的发生。即同时启用上述两者以保证各浏览器的兼容,或者相反,两者皆不启用。
- 使元素即生成了BFC,又触发了 hasLayout
- 对于触发 hasLayout 的元素,通过 CSS 设置,使它产生BFC;
- 生成 BFC但是没有触发 hasLayout 的元素,通过设置 ‘zoom:1’,使其触发 hasLayout。
- 使元素即没有触发 hasLayout,又没有创建 BFC。
margin折叠及hasLayout && Block Formatting Contexts的更多相关文章
- hasLayout && Block Formatting Contexts
转自:http://www.smallni.com/haslayout-block-formatting-contexts/ 因为本人脑子不好使,自己打印出了一张hasLayout和Block For ...
- hasLayout与Block formatting contexts的学习(下)
BFC布局规则: 内部的Box会在垂直方向,一个接一个地放置. Box垂直方向的距离由margin决定.属于同一个BFC的两个相邻Box的margin会发生重叠 每个元素的margin box的左边, ...
- hasLayout与Block formatting contexts的学习(上)
hasLayout与Block formatting contexts的学习 @(css BFC)[IE hasLayout|妙瞳] hasLayout是什么? haslayout 是Windows ...
- 我们常用,却容易忽视——CSS的BFC(Block formatting contexts)
BFC——一个我们容易忽视掉的布局神器 今天给大家说说BFC这个概念,在说概念前,先给大家看个例子: 首先,定义三个div块元素 效果: 我们发现,块级元素的排列顺序是从上往下,一块接着一块,在w ...
- 详说 Block Formatting Contexts (块级格式化上下文)
在上文<详说清除浮动>中,Kayo 较为详细地介绍了 BFC ,也就是本文的主角 Block Formatting Contexts (块级格式化上下文),本文会基于上文关于 BFC 的部 ...
- Block Formatting Contexts (块级格式化上下文) 使用参考
转自:http://kayosite.com/block-formatting-contexts-in-detail.html 在上文<详说清除浮动>中,Kayo 较为详细地介绍了 BFC ...
- Block Formatting Contexts (块级格式化上下文) 详解
最近在学习BootStrap框架,发现里面清除浮动的类 .clearfix 跟平时自己用的不太一样.它的样式是这样的: .clearfix:before { content: " ...
- BFC 详说 Block Formatting Contexts (块级格式化上下文)
定位方案是控制元素的布局,在 CSS 2.1 中,有三种定位方案——普通流 (Normal Flow) .浮动 (Floats) 和绝对定位 (Absolute Positioning) ,下面分别对 ...
- 块级格式化上下文( Block formatting contexts)
那么如何触发BFC呢? float 除了none以外的值 overflow 除了visible 以外的值(hidden,auto,scroll ) display (table-cell,table- ...
随机推荐
- ESRI.ArcGIS.AnalysisTools.Erase 结果是空?
用ESRI.ArcGIS.AnalysisTools.Erase擦除,结果总是空的. 这几天一直纠结一个问题,就是在AE下使用ESRI.ArcGIS.AnalysisTools中的工具(例如:泰森多边 ...
- 整数重复的第n位计算公式
513不停的重复形成513513513....,求第n位是几的计算公式.
- bootstrap-treeview 关于checkbox选择框不显示的问题
bootstrap-treeview.js 1.0.2 不支持checkbox,最后使用 bootstrap-treeview.js 1.2.0 解决此问题.
- eclipse 安装
做一个项目,需要搭建环境.使用sql server 2005,tomcat,eclipse.过程真复杂,碰到些小问题,不过都解决了,还算顺利. win7下sql server 2005安装:http: ...
- Tomcat服务器(一)
一.tomcat目录中重要的文件: bin 存放启动和关闭的脚本 conf 存放配置文件 logs 日志文件 webapps 存放部署的项目 work 工作目录 Web应用开发好后,若想供外界访问, ...
- 移动端与PC端的viewport
第一种解析: 设备像素,就是我们直觉上觉得"靠谱"的像素,这些像素为所使用的各种设备提供了正规的分辨率,并且其值可以通过(通常情况下)从screen.width/height属性中 ...
- Android-ByteUtil工具类
Byte处理转换相关的工具类: public class ByteUtil { private ByteUtil(){} /** * 把byte[] 转成 Stirng * @param bytes ...
- 使用 Project Siena 生成一个 Windows Store 应用
继 App Studio 之后微软又一力作 Project Siena [Win8 应用神器]给初学开发 或 对 Windows Store 应用感兴趣的同学们的一个福利,可以通过 一个简单的应用可以 ...
- [Ubuntu]管理开机启动项的软件
sudo apt-get install sysv-rc-conf
- [.net 多线程]线程基础
一.线程状态 1.新建状态(New): 当用new操作符创建一个线程时, 例如new Thread(r),线程还没有开始运行,此时线程处在新建状态. 当一个线程处于新生状态时,程序还没 ...