发现我好久没更新博文了=-=这里把我之前在博客园写过的一篇关于BFC的文章粘贴过来,顺便自己也再次做个总结。


最近看了一篇总结ie常见bug的文章,里面提到ie多数的bug源于她的特有属性:hasLayout。这个属性以前也了解过一点,但没有深入去理解,于是查阅了一些相关的资料,现在在此来对这个属性作一下总结。

haslayout的普遍定义

洋洋洒洒一大篇。这里的内容如果觉得不好懂的话建议可以先看看后文提到的BFC属性。

在ie中,一个元素要么自己对自身的内容进行计算大小和组织,要么依赖于父元素来计算尺寸和组织内容。为了调节这两个不同的概念,渲染引擎采用了
hasLayout 的属性,属性值可以为true或false。当一个元素的
hasLayout属性值为true时,我们说这个元素有一个布局(layout)。

如果它设置成了true,它就不得不去渲染它自己,因此元素不得不扩展去包含它的流出的内容。例如浮动或者很长很长的没有截断的单词,如果haslayout没有被设置成true,那么元素得依靠某个祖先元素来渲染它。这就是很多的ie
bugs诞生的地方。

当一个元素有一个布局时,它负责对自己和可能的子孙元素进行尺寸计算和定位。简单来说,这意味着这个元素需要花更多的代价来维护自身和里面的内容,而不是依赖于祖先元素来完成这些工作。因此,一些元素默认会有一个布局。当我们说一个元素“拥有layout”或 “得到layout,

或者说一个元素“has layout” 的时候,我们的意思是指它的微软专有属性 hasLayout 被设为了 true。通过IE Developer Toolbar 可以查看 IE 下 HTML元素是否拥有haslayout,在 IE Developer Toolbar 下,拥有 haslayout的元素,通常显示为“haslayout = -1”。

  值得注意的是,css下是没有haslayout这一个属性的,只能通过把某些属性设置特定值来使ie下的hasLayout属性触发。这个属性在ie8及以后版本中被抛弃。

激活“haslayout”的方式——调整下列css属性:

  • width:非auto任意值——优先考虑

  • height:非auto任意值——对 IE6 及更早版本来说很常用,该方法被称为霍莉破解(Holly hack),即设定这个元素的高度为 1% (height:1%;)。但是要注意,当这个元素的 overflow 属性被设置为 visible 时,这个方法就失效了。

  • zoom:非normal任意值——该属性也为ie特有属性。一般测试的时候用zoom:1。可以避免改变其他属性破坏布局。

  • position:absolute——可能引发新问题。

  • float:left/right——ie 常见bug很多都因为元素设置了浮动而触发haslayout产生的。

  • display:inline-block——当一个内联元素想获得layout就要使用这个属性。

  • min-heightmax-height(除none)、min-widthmax-width(除none)设置任意值——针对ie7。

  • overflowoverflow-xoverflow-yvisible外任意值——针对ie7。

  • position:fixed——针对ie7。

重置“haslayout”:需要没有其他属性激活haslayout的前提下。

  • width, height (设为 "auto")

  • max-width, max-height (设为 "none")(在 IE 7 中)

  • position (设为 "static")

  • float (设为 "none")

  • overflow (设为 "visible") (在 IE 7 中)

  • zoom (设为 "normal")

  • writing-mode (从 "tb-rl" 设为 "lr-t")

注意:当用inline-block激活了haslayout 属性时,就算在一条独立的规则中覆盖这个属性为blockinline,haslayout 这个标志位也不会被重置为 false。把 min-width, min-height 设为它们的默认值"0"仍然会赋予 hasLayout,但是 IE 7 却可以接受一个不合法的属性auto来重置 hasLayout。


块级格式化上下文BFC

BFC是W3C CSS 2.1
规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。当涉及到可视化布局的时候,Block Formatting Context提供了一个环境,HTML元素在这个环境中按照一定规则进行布局。一个环境中的元素不会影响到其它环境中的布局。

要更好地理解BFC,要先来谈谈Box和Formatting Context的概念。我们知道网页布局是由很多盒子组成的,这些块就是Box。元素的类型和 display 属性,决定了这个 Box 的类型。 不同类型的 Box, 会参与不同的 Formatting Context(决定如何渲染文档的格式结构),因此Box内的元素会以不同的方式渲染。

例如:

  • block-level box: display 属性为 block, list-item, table 的元素,会生成
    block-level box。并且参与 block fomatting context;

  • inline-level box:display 属性为 inline, inline-block, inline-table
    的元素,会生成 inline-level box。并且参与 inline formatting context;

而Formatting Context是一块渲染区域,它决定了其子元素如何定位,以及与其他元素的位置关系。

根据上述的一些基本概念,我把BFC简单理解成一种属性,在具有BFC属性的容器中,元素按照BFC的规则实现布局。比如浮动元素会形成BFC,这就是为什么我们看到浮动元素布局跟普通文档流下的布局有所差别的原因。

BFC的规则

  • 内部的Box会在垂直方向,一个接一个地放置。

  • Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠

  • 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。

  • BFC的区域不会与float box重叠。

  • BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。

  • 计算BFC的高度时,浮动元素也参与计算

哪些元素会形成BFC

  • 根元素

  • float属性不为none

  • position为absolute或fixed

  • display为inline-block, table-cell, table-caption, flex, inline-flex

  • overflow不为visible
     

BFC在布局中的作用

  • 解决两元素margin重叠的问题

    要想两个相邻的元素不发生垂直方向上的margin重叠,需要将他们两定义在不同的BFC中。解决方法即在其中一个元素外包裹一层元素,再对那层包裹的元素进行BFC触发。(这里可以加入上述的css属性。)

  • 解决由于浮动造成的重叠问题

    一般情况下,浮动元素会脱离文档流,即不占位置。它的兄弟元素会与它在左上角重叠。但是如果两个相邻元素都设置了浮动,那么意味着它们都是以BFC的规则渲染,根据上述第四条规则,BFC区域不会相互重叠,所以便能理解为什么设置浮动后元素能独占空间了。

  • 解决容器由于拥有浮动元素造成高度塌陷的问题

    在普通容器中,如果里面有浮动元素,在不设置高度的情况下,容器是不能被撑起来的,这时候通过设置overflow:hidden把其变为BFC,那么就可以包含浮动元素了。


BFC的说明到此就告一段落了,现在回到最初讨论的haslayout的问题。ie7及以下ie版本不支持BFC的,但有私有属性haslayout,于是我们可以通过触发元素的haslayout来达成bfc的相似效果。

IE下因为haslayout导致的bug

1、浮动元素与普通元素之间产生3px bug

//代码如下
<style>
.test {width: 800px;margin: 10px auto;border: 1px solid brown;height: 30px;}
.float {float: left;background: saddlebrown;color: #fff;}
}
</style><div class="test"><div class="float">我是浮动元素</div>我是后面的文字,用来测试3px的bug
</div>

正常情况:

ie6下:

解决方式:加一个ie6的hack:*margin-right:-3px;

不只是文字,ie6的浮动元素也会和内联元素产生3px的margin值。

正常情况:

ie6,7下:

解决方式同上。

2、块级元素与浮动元素不会重叠

   <style>.test {width: 800px;margin: 10px auto;border: 1px solid brown;height: 30px;}.float {float: left;background: saddlebrown;color: #fff;}}</style><div class="test"><div class="float">我是浮动元素</div><div style="background: #0079F5;height: 30px;">我是浮动元素后面的块级元素</div></div>

正常情况:

ie6,7:

可以明显地发现ie6,7下块级元素跟浮动元素不能重叠。为什么会发生这种情况呢?是因为我在块级元素上设置了高度。激活了ie下的haslayout属性。于是ie6把它以BFC类似的方式进行渲染。

解决方式:在块级元素外再包裹一层DIV。并且把内部DIVbackground的属性写在外层DIV上。

3、浮动闭合元素
这个问题其实很多人会遇到,上文也提到过,只是可能叫法不同。

<style>
.test {width: 800px;margin: 10px auto;border: 1px solid brown;}
.float {float: left;background: saddlebrown;color: #fff;}
</style><div class="test"><div class="float">我浮动啦!</div>
</div>

正常情况:

注意那一条横线是.test的border,因为浮动元素脱离了文档流,故.test不能被撑起来。

ie6,7

ie似乎妥妥的。其实很多情况下,我们想要的是ie这种效果。在ie中,一个浮动元素总是隶属于包含它的容器。是因为.test设置了宽度,激活了haslayout属性。而在非ie浏览器中,我们想要获得这种效果一般是在父盒子上加一个:after的伪对象来清除浮动,或者设置overflow:hidden来触发BFC。

插入提一下闭合浮动的普遍做法:
为需要闭合浮动的父元素加入clearfix的类。

.clearfix::after {content:"";display:block;height:0;clear:both;}
.clearfix {zoom: 1;} //兼容ie6,7

4、ie下margin不塌陷

<style>
.test {width: 800px;margin: 10px auto;}
.float {float: left;background: saddlebrown;color: #fff;}
</style><div class="test"><div class="float">我浮动啦!</div><div style="margin-top:30px;">测试margin-top在ie下是否塌陷</div>
</div>

正常情况:

ie6,7

float是浮动元素,她脱离了文档流,所以第二个DIV的margin-top相对的是其上级.test作用的。但我们只是对第二个DIV设置margin-top。结果在chrome下,怎么连float也“产生了margin-top”呢。对比ie和chrome下的效果,是不是觉得IE下的 解析会比较合理呢?

但是。别忘了影响margin-top/bottom的一个重要规则——margin塌陷(margin collapsing)。

提到了margin塌陷,我们来看看margin垂直方向上塌陷的一些条件: 

  • 水平margin不会合并。

  • 两个上下渲染相邻(不一定是兄弟节点)的块状元素在正常页面流情况下会发生 margin 合并。

  • 浮动元素不会和任何元素(包括子孙节点)发生 margin 合并。

  • overflow!=visible的元素不和任何元素发生margin合并。

  • 绝对定位的元素不和任何元素发生margin合并。

  • inline-block 的元素不和任何元素发生margin合并。

  • 设置 clear 属性的元素不和任何元素发生margin合并。

  • 根元素不和任何元素发生margin合并。

  • 父节点和第一个子节点发生margin-top合并。

  • 如果最后一个子节点没有border以及padding,则和其父节点发生margin-bottom合并。

注意低版本IE下特别是hasLayout对于margin合并也有影响,从而也造成了包含的绝对定位元素的位置差异。

在现代浏览器下.test块的高度并没有被子元素第二个DIV的margin-top撑开。反而自身拥有了30px的margin-top
而浮动块尽管脱离了文档流,但还是受其父级限制的(这跟absolute定位的元素层受限于其定义为relative的父级一样)。所以float还是包含在test之中,这样在chrome下看起来浮动块也拥有margin-top,而事实上是因为test高度不撑开的结果。

这么说,chrome并没有错咯,那么IE下又是怎么避开margin塌陷的呢?问题就出在浮动上面,在ie下,元素浮动将触发其haslayout。就是这个原因,使得在ie下意外(意外?)的就避开了margin塌陷。

但是奇怪的是,如果给.test加上border,chrome的渲染情况就跟ie一样了,float没有拥有与第二个DIV相同的margin-top值。而是紧贴.test的顶部。如下图:

chrome:

ie6,7:

这个问题的原因还需要研究一下。。。。如果有知道原因的大神麻烦给留个言,,感激!

5、ie下margin-left/right失效

<style>
.test {margin: 10px auto;border:1px solid darkred;}
</style><div class="test"><div style="height:30px;margin:0 20px;border-bottom: 3px solid sandybrown;">测试失效的margin-left</div>
</div>

正常情况:

ie6:

根据上图可以发现,ie下我们为子DIV设置的margin失效了。为什么会发生这种情况,同样是是因为子DIV设置了高度,激活了haslayout。

解决办法:不为子DIV设置高度,或者把父盒子的haslayout也激活。

参考资料:
http://cssass.com/blog/2009/147.html
http://www.cnblogs.com/lhb25/p/inside-block-formatting-ontext.html
http://www.cnblogs.com/pigtail/archive/2013/01/23/2871627.html

原文链接:
http://www.cnblogs.com/Remix/articles/4777257.html

谈谈BFC与ie特有属性hasLayout相关推荐

  1. 谈谈BFC与ie特有属性hasLayout 1

    最近看了一篇总结ie常见bug的文章,里面提到ie多数的bug源于她的特有属性:hasLayout.这个属性以前也了解过一点,但没有深入去理解,于是查阅了一些相关的资料,现在在此来对这个属性作一下总结 ...

  2. php斯芬克斯,斯芬克斯之迷——ie私有属性haslayout的困扰

    就象神话中的斯芬克斯一样,ie的私有属性haslayout是个神秘且让人困惑的难缠东西,她只游荡于ie(这片沙漠)之下. 她无法使用css声明直接创建.即便是对于ie,她也不能说是一个实实在在存在的属 ...

  3. Android应用开发(1)---Android五大UI布局的特有属性

    Android五大UI布局的特有属性 Android五大UI布局 1. LinearLayout 线性布局 2. RelativeLayout 相对布局 3. FrameLayout 帧布局,空白布局 ...

  4. Java/java程序设计多态参数:练手小题:父类员工类含有普通员工和经理两个子类,普通员工有work方法,经理有特有属性年终奖,和manage方法现要求在主文件中设计能调用所有类的年薪方法和工作方法

    多态参数:练手小题 1. 前言: 2. 分析需求: 2.1 主类Employee分析 2.1.1 主类Employee代码片段 2.2 子类work普通员工分析 2.2.1 子类work普通员工代码片 ...

  5. ASP.NET Core教程【二】从保存数据看Razor Page的特有属性与服务端验证

    前文索引: ASP.NET Core教程[一]关于Razor Page的知识 在layout.cshtml文件中,我们可以看到如下代码: <a asp-page="/Index&quo ...

  6. Python进阶-----面向对象2.0(特有属性和方法与私有属性和方法)

    目录 前言: 1.添加特有属性/方法 示例1:添加特有属性 示例2:添加特有方法 2.私有属性/方法 (1)私有化示例 (2) 私有化属性/方法可以在类的内部使用 (3)强制访问私有化属性/方法 (4 ...

  7. CSS魔法堂:hasLayout原来是这样!

    前言 过去一直听说旧版本IE下很多诡异bug均由一个神秘角色引起的,那就是hasLayout.趁着最近突然发神经打算好好学习CSS,顺便解答多年来的疑惑. hasLayout到底是何方神圣? hasL ...

  8. 【百度前端学院学习笔记】Day6 浮动/BFC

    [百度前端学院学习笔记]Day6 浮动/BFC 一.什么是浮动? 二.普通流 / 浮动 / 绝对定位 三.BFC/Flow Root 3.1 什么是BFC? 3.2 BFC 的特性 3.2.1 特性一 ...

  9. 深入理解盒子模型——CSS视觉格式化模型|盒模型|定位方案|BFC

    视觉格式化模型 页面(文档树)可以想象成是由一个个的Box组合而成的,而视觉格式化模型(Visual formatting model)是一套规则,将这些框布局成访问者看到的样子. 哪些因素控制了这些 ...

  10. web前端面试基本知识重点(下)

    46.iframe有那些缺点? (1)页面样式调试麻烦,出现多个滚动条: (2)浏览器的后退按钮失效: (3)过多会增加服务器的HTTP请求: (4)小型的移动设备无法完全显示框架: (5)产生多个页 ...

最新文章

  1. VS2010运行类向导提示“未实现该方法或操作”
  2. Python 基础整理(未完)
  3. lnmp.org + phpstorm + xdebug
  4. NET插件系统之四——提升系统搜索插件和启动速度的思考
  5. 创建自定义Widgets小部件扩展
  6. java可视化压缩_web可视化技术发展(1/6)
  7. mydumper备份原理和使用方法
  8. vue表单的基本使用
  9. 服务器上域名打不开网站,域名打不开网站
  10. uva 1328(kmp)
  11. Adobe Acrobat软件安装步骤
  12. 联众打码写滑动_自己写了一个答题的软件现在分享一下(在分享一下联众打码源码调用) _ 综合讨论 - 按键精灵论坛...
  13. 清华大学829考研 初试436经验谈
  14. 聚类分析q型matlab,Q型聚类分析
  15. MFC 通用对话框之“查找替换“对话框
  16. C语言变量及其生命周期
  17. 圣诞表白html,Pyhton表白代码——浪漫圣诞节
  18. 华硕路由虚拟服务器设置方法,华硕路由虚拟服务器设置方法
  19. python -u xxx.py
  20. VS2019 Community许可证过期

热门文章

  1. python中的字典操作_python中的字典以及相关操作
  2. go语言 读文件最后一行_Go 语言核心文件调试
  3. php 实现静态链接,在PHP中链接静态方法?
  4. 制作android刷机补丁update.zip 的步骤,android-update.zip 刷机包制作教程.pdf
  5. matlab三维矩阵的运算符,【求助】多维矩阵求和运算!!
  6. python学习_Python学习 基础篇完结
  7. LeetCode 1——两数之和
  8. 与JavaWeb有关的故事(Web请求与Java IO)
  9. LINQToSQL中如何更好的手动设置导航字段,并返回实名类型而不是匿名类型
  10. angular中的装饰器 详解