BFC给我的帮助以及对hasLayout的认识

布局的时候经常想让一个或几个元素并并排的放在一起,有时给其中的一个浮动,元素是在一行了,可还是都左边重叠了,总是这样那样改来改去,小白的我也是醉了!

今天偶然间看到了了BFC这个东东,虽然现在还是不是很深入的了解,但至少一行不用在在上面的问题上浪费时间了(捂脸)。

一、什么是BFC?

BFC(Block Formatting Context)直译为“块级格式化范围”。

 W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用当涉及到可视化布局的时候,Block Formatting Context提供了一个环境,HTML元素在这个环境中按照一定规则进行布局。一个环境中的元素不会影响到其它环境中的布局。比如浮动元素会形成BFC,浮动元素内部子元素的主要受该浮动元素影响,两个浮动元素之间是互不影响的。这里有点类似一个BFC就是一个独立的行政单位的意思。也可以说BFC就是一个作用范围。可以把它理解成是一个独立的容器,并且这个容器的里box的布局,与这个容器外的毫不相干。

另一个通俗点的解释是:在普通流中的 Box(框) 属于一种 formatting context(格式化上下文) ,类型可以是 block ,或者是 inline ,但不能同时属于这两者。并且, Block boxes(块框) 在 block formatting context(块格式化上下文) 里格式化, Inline boxes(块内框) 则在 inline formatting context(行内格式化上下文) 里格式化。任何被渲染的元素都属于一个 box ,并且不是 block ,就是 inline 。即使是未被任何元素包裹的文本,根据不同的情况,也会属于匿名的 block boxes 或者 inline boxes。所以上面的描述,即是把所有的元素划分到对应的 formatting context 里。

 二、怎样产生BFC?

 当一个HTML元素满足下面条件的任何一点,都可以产生

float值不为none;

overflow值不为visible;

display值为inline-block,table-cell,table-caption中的任意一个;

postion值不为relative和static;

三、BFC的作用

记录一下自己刚写的时候常遇到的情况:

情况1:一个浮动元素后面跟着一个没有浮动的元素,两个元素会重叠在一起。当时为了拆散他俩,内边距,外边距什么都用了,想想也是够难为自己的。

 

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8"/>
<title>生成BFC元素和浮动元素在一起不会重叠</title>
<style type="text/css">
* { padding:0; margin:0; color:#fff; text-decoration:none; list-style:none; font-family:"微软雅黑" }

.div1{
float:left;
width:200px;
height:400px;
background:red;

}
.div2{
overflow:hidden;//生成BFC
width:300px;
height:500px;
background:blue;
}
</style>
</head>
<body>

<div class="div1"></div>
<div class="div2"></div>

</body>
</html>

 

根据 CSS 2.1 9.5 Floats 中的描述,创建了 Block Formatting Context 的元素不能与浮动元素重叠。

   表格的 border-box、块级的替换元素、或是在普通流中创建了新的 block formatting context(如元素的 'overflow' 特性不为 'visible' 时)的元素不可以与位于相同的 block formatting context 中的浮动元素相重叠。所以给div2添加overfl:hidden.

ie的原因需要再加一个解发haslayout的zoom:1

情况2:让拥有浮动子元素的父元素获取高度。

如果一个父元素的子元素浮动的话,其父元素是不计算其的高度的,情况就成了这样的了,o(╯□╰)o

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8"/>
<title>生成BFC元素的浮动子元素也参与高度计算</title>
<style type="text/css">
* { padding:0; margin:0; color:#fff; text-decoration:none; list-style:none; font-family:"微软雅黑" }
.big{
overflow:hidden;//针对图片3
width:300px;
border:1px solid #666;
padding:10px;
}
.div1{
float:left;
width:200px;
height:50px;
background:red;

}
.div2{
float:left;
width:200px;
height:50px;
background:blue;

}
</style>
</head>
<body>
<div class="big">
<div class="div1"></div>
<div class="div2"></div>
</div>

</body>
</html>

     图片2

根据 CSS2.1 规范第 10.6.3 部分的高度计算规则,在进行普通流中的块级非替换元素的高度计算时,浮动子元素不参与计算。

同时 CSS2.1 规范第10.6.7部分的高度计算规则,在计算生成了 block formatting context 的元素的高度时,其浮动子元素应该参与计算。

所以,触发外部容器BFC,高度将重新计算。比如给big加上属性overflow:hidden触发其BFC。

 生成BFC之后的效果:

       图片3

 情况3:两个上下相邻元素设置分别给其设置margin-bottom和margin-top值时会重叠。

 

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8"/>
<title>相邻的两个盒子的margin值会重叠</title>
<style type="text/css">
* { padding:0; margin:0; color:#fff; text-decoration:none; list-style:none; font-family:"微软雅黑" }
.div1{
width:200px;
height:50px;
background:red;
margin-bottom:20px;
}
.div2{
width:200px;
height:50px;
background:blue;
margin-top:20px;
}
</style>
</head>
<body>

<div class="div1"></div>
<div class="div2"></div>
</body>
</html>

     图片4

根据 CSS 2.1 8.3.1 Collapsing margins 第一条,两个相邻的普通流中的块框在垂直位置的空白边会发生折叠现象。也就是处于同一个BFC中的两个垂直窗口的margin会重叠。

根据 CSS 2.1 8.3.1 Collapsing margins 第三条,生成 block formatting context 的元素不会和在流中的子元素发生空白边折叠。所以解决这种问题的办法是要为两个容器添加具有BFC的包裹容器。

所以解这个问题的办法就是,把两个容器分别放在两个据有BFC的包裹容器中,IE里就是触发layout的两个包裹容器中!

 

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8"/>
<title>相邻的两个盒子的margin值会重叠</title>
<style type="text/css">
* { padding:0; margin:0; color:#fff; text-decoration:none; list-style:none; font-family:"微软雅黑" }
.big{
overflow:hidden;
}
.div1{
width:200px;
height:50px;
background:red;
margin-bottom:20px;
}
.div2{
width:200px;
height:50px;
background:blue;
margin-top:20px;
}
</style>
</head>
<body>
<div class="big">
<div class="div1"></div>
</div>
<div class="big">
<div class="div2"></div>
</div>

</body>
</html>

    图片5

 平时也会看到很多这些情况,但很少自己动手做的,今天就给自己加深加深也学习学习BFC东东!

BFC篇完结了!

关于更详细的请查看穆乙 http://www.cnblogs.com/pigtail/

什么是IE的haslayout

上面的例子中我们用到了IE的zoom:1;实际上是触发了IE的layout。Layout 是 IE 浏览器渲染引擎的一个内部组成部分。在 IE 浏览器中,一个元素要么自己对自身的内容进行组织和计算大小, 要么依赖于包含块来计算尺寸和组织内容。为了协调这两种方式的矛盾,渲染引擎采用了 ‘hasLayout’ 属性,属性值可以为 true 或 false。 当一个元素的 ‘hasLayout’ 属性值为 true 时,我们说这个元素有一个布局(layout),或拥有布局。可以通过 hasLayout 属性来判断一个元素是否拥有 layout ,

如 object.currentStyle.hasLayout 。

hasLayout 与 BFC 有很多相似之处,但 hasLayout 的概念会更容易理解。在 Internet Explorer 中,元素使用“布局”概念来控制尺寸和定位,分为拥有布局和没有布局两种情况,拥有布局的元素由它控制本身及其子元素的尺寸和定位,而没有布局的元素则通过父元素(最近的拥有布局的祖先元素)来控制尺寸和定位,而一个元素是否拥有布局则由 hasLayout 属性告知浏览器,它是个布尔型变量,true 代表元素拥有布局,false 代表元素没有布局。简而言之,hasLayout 只是一个 IE 下专有的属性,hasLayout 为 true 的元素浏览器会赋予它一系列的效果。

特别注意的是,hasLayout 在 IE 8 及之后的 IE 版本中已经被抛弃,所以在实际开发中只需针对 IE 8 以下的浏览器为某些元素触发 hasLayout。

 

五、怎样触发layout

一个元素触发 hasLayout 会影响一个元素的尺寸和定位,这样会消耗更多的系统资源,因此 IE 设计者默认只为一部分的元素触发 hasLayout (即默认有部分元素会触发 hasLayout ,这与 BFC 基本完全由开发者通过特定 CSS 触发并不一样),这部分元素如下:

复制代码
<html>, <body>
<table>, <tr>, <th>, <td>
<img>
<hr>
<input>, <button>, <select>, <textarea>, <fieldset>, <legend>
<iframe>, <embed>, <object>, <applet>
<marquee>
复制代码

除了 IE 默认会触发 hasLayout 的元素外,Web 开发者还可以使用特定的 CSS 触发元素的 hasLayout 。

通过为元素设置以下任一 CSS ,可以触发 hasLayout (即把元素的 hasLayout 属性设置为 true)。

复制代码
display: inline-block
height: (除 auto 外任何值)
width: (除 auto 外任何值)
float: (left 或 right)
position: absolute
writing-mode: tb-rl
zoom: (除 normal 外任意值)
min-height: (任意值)
min-width: (任意值)
max-height: (除 none 外任意值)
max-width: (除 none 外任意值)
overflow: (除 visible 外任意值,仅用于块级元素)
overflow-x: (除 visible 外任意值,仅用于块级元素)
overflow-y: (除 visible 外任意值,仅用于块级元素)
position: fixed
复制代码

对于内联元素(可以是默认被浏览器认为是内联元素的 span 元素,也可以是设置了 display: inline 的元素),width 和 height 只在 IE5.x 下和 IE6 或更新版本的 quirks 模式下能触发元素的 hasLayout ,但是对于 IE6,如果浏览器运行于标准兼容模式下,内联元素会忽略 width 或 height 属性,所以设置 width 或 height 不能在此种情况下令该元素触发 hasLayout 。但 zoom 除了在 IE 5.0 中外,总是能触发 hasLayout 。zoom 用于设置或检索元素的缩放比例,为元素设置 zoom: 1 既可以触发元素的 hasLayout 同时不会对元素造成多余的影响。因此综合考虑浏览器之间的兼容和对元素的影响, 建议使用 zoom: 1 来触发元素的 hasLayout 。

六、能解决的问题

hasLayout表现出来的特性跟BFC很相似,所以可以认为是IE中的BFC。上面的规则几乎都遵循,所以上面的问题在IE里都可以通过触发hasLayout来解决。

虽然 hasLayout 也会像 BFC 那样影响着元素的尺寸和定位,但它却又不是一套完整的标准,并且由于它默认只为某些元素触发,这导致了 IE 下很多前端开发的 bugs ,触发 hasLayout 更大的意义在于解决一些 IE 下的 bugs ,而不是利用它的一些“副作用”来达到某些效果。另外由于触发 hasLayout 的元素会出现一些跟触发 BFC 的元素相似的效果,因此为了统一元素在 IE 与支持 BFC 的浏览器下的表现,Kayo 建议为触发了 BFC 的元素同时触发 hasLayout ,当然还需要考虑实际的情况,也有可能只需触发其中一个就可以达到表现统一,下面会举例介绍。

这里首先列出触发 hasLayout 元素的一些效果:

a、阻止外边距折叠

 如上面例子:

复制代码
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>无标题文档</title>
<style>
html, body { height:100%; }
* { padding:0; margin:0; color:#fff; text-decoration:none; list-style:none; font-family:"微软雅黑" }
.mg {zoom:1}
.rowone { background:#f00; height:100px; margin-bottom:20px; }
.rowtow { background:#090; height:100px; margin-top:20px; }
</style>
</head>

<body>
<div class="mg">
    <div class="rowone">
    </div>
</div>
<div class="mg">
    <div class="rowtow">
    </div>
</div>
</body>
</html>
复制代码

需要触发.mg的layout才能解决margin重叠问题

运行效果如下:

 

posted @ 2015-06-25 13:56  素雨雫晴  阅读(242)  评论(0编辑  收藏  举报