浮层的原理与清除
1、为什么会产生浮层
?
首先我们看一下float这个属性,套用w3c标准,对该属性的定义如下:
?
?
float 属性定义元素在哪个方向浮动。以往这个属性总应用于图像,使文本围绕在图像周围,不过在 CSS 中,任何元素都可以浮动。浮动元素会生成一个块级框,而不论它本身是何种元素。
?
如果浮动非替换元素,则要指定一个明确的宽度;否则,它们会尽可能地窄(根据内容来计算其宽度,如果没有内容也没有设置该浮动层的宽度,则该浮动层在页面中是看不见的)。
?
注释:假如在一行之上只有极少的空间可供浮动元素,那么这个元素会跳至下一行,这个过程会持续到某一行拥有足够的空间为止
?
设置了该属性的left或right值后,该浮动元素(floats)就会被移出文档流。这就产生了一个问题:浮动元素所在父元素不会自动伸长以便闭合浮动元素。看下面的代码
?
?
<div id="outer"> <div id="inner"> <h2>A Column</h2> </div> <h1>Main Content</h1> <p>Lorem ipsum</div>
? ? ??我们可以为“#inner”设定一个宽度值(比如说20%),但是由于div是块级元素,即使我们设定了宽度,其后面的内容也只能在下一行中显示,除非我们给它设定一个浮动属性(无论是向左浮动或者向右浮动)。那么此时会产生我们上面提到的问题了。
? ? ? 如果“#inner”的宽度和高度都比“#outer”小,这不会有问题。
? ? ? 但是,如果“#inner”的高度超过了“#outer”,那么的底部就会超出“#outer”的底部。这是因为我们为“#inner”设定了float属性后,它就会脱离文档流,无论其宽度和高度怎么变化都不会使“#outer”跟随变化。
?
? ? ? 看下面代码:设置浮动层后,由于inner的高度超出了outer的高度,他会浮动起来,脱离文档流,而outer下面的div元素会根据outer的高度来定位自己的位置,这时outer没有自动变化高度,所以outer下面的元素就会显示在浮动层的右侧,在各主流浏览器都是这个效果。
?
?
<div id="outer" style="border:1px solid #f2f2f2;"><div id="inner" style="float:left;height:300px;"><h2>A Column</h2></div><h1>Main Content</h1><p>Lorem ipsum</p></div><div>有浮层显示的效果</div>
? ? ?如果我们在定义了浮动层影响父元素的内部加上清除浮动的方法后,页面就会正常显示,看下面代码
?
?
<div id="outer" style="border:1px solid #f2f2f2;"><div id="inner" style="float:left;height:300px;"><h2>A Column</h2></div><h1>Main Content</h1><p>Lorem ipsum</p><div style="clear:both;"></div></div><div>有浮层显示的效果</div>
?
? ? ?在浏览器中再次预览效果,发现页面正常显示了,这里要说一点,就是浮动清除元素放到哪个位置,应该放到inner的下面(不一定紧挨着inner)。
?
2、?浏览器中可以自动完成闭合浮动元素的情况(即子元素设置了浮层,但父元素会自动撑开高度)
?
?
? ? 2.1、标准浏览器中可以自动完成闭合浮动元素的方法,在标准浏览器中,这称之为Block-Formatting-Contexts(块格式化上下文):
? ? ? ?a.浮动元素;
? ? ? ?b.拥有绝对定位属性的元素;
? ? ? ?c.设置inline-block元素;
? ? ? ?d.table-cell元素;
? ? ? ?e.设置了overflow的元素,比如:auto/hidden。
【注】CSS3中,将Block-formatting-contexts 叫做 flow root。对于触发方式也做了修改:The value of ‘position’ is neither ‘static’ nor ‘relative’;
?
? ? ? ?那么在IE/win中,就依靠那个“hasLayout”了,触发“layOut”的方法有:
? ? ? ?a.浮动元素
? ? ? ?b.绝对定位元素
? ? ? ?c.display:inline-block
? ? ? ?d.zoom:比如常见的设置zoom:1;
? ? ? ?e.width/height,比如设置height:1%的方法;
? ? ? ?f.overflow/overflow-x/overflow-y [IE7 新增];
? ? ? ?g.max/min-width/height [IE7 新增];
?
? ?这里简单的举一个例子,看以下代码
?
?
<div>浮动中套浮动的效果</div><div style="border: 1px solid #f2f2f2;"><div style="float: right;"><div style="float: left; height: 100px; border: 1px solid #f2f2f2;">由于父元素也是浮层,所以会自动闭合浮动层的(即父元素自适应高度的)</div><div>内容</div></div><div style="clear: both;"></div></div>
?
? 最里边的浮动层由于父元素设置了浮动层,所以会自动闭合的
?
3、清除浮动常见方法
?
? ? 我们知道了产生浮动的原理并且各浏览器清除浮层的不同后,清除浮动就好办了。主要有以下几种方式
?
?
? ?(1)空标签法:
? ? ? ?这种方法应该说是最简单的一种了,W3C建议在容器的末尾增加一个“clear:both"的元素,强迫容器适应它的高度以便装下所有的float,并没限制使用什么样的标签,有用<br style=”clear:both”/>的,有用空<div style=”clear:both”></div>的;比如:?
?
?
<div> <div style ="float:left; width:40%;"> <p> Some content </p> </div> <p> Text outside the float </p> <div style ="clear:both;" ></div> </div>
?
?
(2)父元素使用overflow的方法:
? ? ? ?通过设置父元素overflow值设置为hidden或者auto;不过,在<=IE6中使用这个方法,还需要haslayout,还有,使用overflow=hidden的时候,一旦你有定位需求可能会因此而难以实现,使用这种方法前你应该至少确定:
? ? ? ?a.父元素的height是自适应的;
? ? ? ?b.浮动元素的宽度不大于父元素的宽度,即没有溢出需求;所以,这种方法也有它的局限性;
?
?
<div style ="overflow:hidden; width:100%;"> <div style ="float:left;width:30%;" > <p>the widths of the combined floats never exceed the width of the container</p> </div></div>
?(3)伪类:after
? ? ? ?这种方法应该说是目前应用最广泛的方法,它的优势:没有多余的标记添加到容器中;通过使用:after产生的content不能接受某些属性,包括'position','float',列表属性,表格属性,但是clear属性可以被接受。
? ? ? ?不过,不幸的是,IE不支持:after方法,但又幸运的是,回顾前面,如果IE在父容器拥有Width/Height等layout状态下,会完成自动闭合,称之为“auto-clearing”;那么,对于IE/win,我们使用设定zoom:1的方法的方法来实现和:after一样的效果.于是一个类似这样的样式出现了:
?
?
.clearfix:after{ content:"."; display:block; height:0; clear:both; visibility:hidden;}.clearfix{zoom:1;}
? ? 上面的代码应该是现在主流的清理浮动方式。现在支付宝就使用这样的方式。另外还有一种更简洁的方案:
?
(4)伪类:before和:after结合使用
?
?
.cf:before, .cf:after { content:""; display:table;}.cf:after { clear:both;}.cf { zoom:1;}
? ? ?原理跟第三种是一样的。使用 :after 伪类来提供浮动块后的 clear:both。不同的是,隐藏这个空白使用的是 display: table。而不是设置 visibility:hidden;height:0;font-size:0; 这样的 hack。
? ? ?值得注意的是这里中的 :before 伪类。其实他是来用处理 top-margin 边折叠的,跟清理浮动没有多大的关系。但因为浮动会创建 block formatting context,这样浮动元素上的另一元素上如果刚好有 margin-bottom 而这个浮动元素刚好有margin-top 的话,应该让他们不折叠(虽然这种情况并不常见)。