那些年我们一起清除过的浮动

本文纯属转载,只是部分内容,全文请拜读原文

前言:本文只转载原博文部分内容,稍加排版编辑;想要详细学习,请拜读原文,感谢一丝冰凉(原文作者),并对原作者花费三天时间来写这篇博文的做法致已崇高的敬意

article_face

浮动(float),一个我们即爱又恨的属性。爱,因为通过浮动,我们能很方便地布局; 恨,浮动之后遗留下来太多的问题需要解决,特别是IE6-7(以下无特殊说明均指 windows 平台的 IE浏览器)。也许很多人都有这样的疑问,浮动从何而来?我们为何要清除浮动?清除浮动的原理是什么?本文将一步一步地深入剖析其中的奥秘,让浮动使用起来更加得心应手。

一、清除浮动 还是 闭合浮动 (Enclosing float or Clearing float)?

很多人都已经习惯称之为清除浮动,以前我也一直这么叫着,但是确切地来说是不准确的。我们应该用严谨的态度来对待代码,也能更好地帮助我们理解开头的三个问题。

1、清除浮动:清除对应的单词是 clear,对应CSS中的属性是 clear:left | right | both | none;

2、闭合浮动:更确切的含义是使浮动元素闭合,从而减少浮动带来的影响。

两者的区别 请看优雅的 Demo;

通过以上实例发现,其实我们想要达到的效果更确切地说是闭合浮动,而不是单纯的清除浮动,在footer上设置clear:both清除浮动并不能解决wrap高度塌陷的问题。

结论:用闭合浮动比清除浮动更加严谨,所以后文中统一称之为:闭合浮动。

二、为何要闭合浮动?

要解答这个问题,我们得先说说CSS中的定位机制:普通流,浮动,绝对定位 (其中”position:fixed” 是 “position:absolute” 的一个子类)。

1、普通流:很多人或者文章称之为文档流或者普通文档流,其实标准里根本就没有这个词。如果把文档流直译为英文就是 document flow ,但标准里只有另一个词,叫做 普通流 (normal flow),或者称之为常规流。但似乎大家更习惯文档流的称呼,因为很多中文翻译的书就是这么来的。比如《CSS Mastery》,英文原书中至始至终都只有普通流 normal flow(普通流) 这一词,从来没出现过document flow (文档流)

2、浮动:浮动的框可以左右移动,直至它的外边缘遇到包含框或者另一个浮动框的边缘。浮动框不属于文档中的普通流,当一个元素浮动之后,不会影响到块级框的布局而只会影响内联框(通常是文本)的排列,文档中的普通流就会表现得和浮动框不存在一样,当浮动框高度超出包含框的时候,也就会出现包含框不会自动伸高来闭合浮动元素(“高度塌陷”现象)。顾名思义,就是漂浮于普通流之上,像浮云一样,但是只能左右浮动。

正是因为浮动的这种特性,导致本属于普通流中的元素浮动之后,包含框内部由于不存在其他普通流元素了,也就表现出高度为0(高度塌陷)。在实际布局中,往往这并不是我们所希望的,所以需要闭合浮动元素,使其包含框表现出正常的高度。

绝对定位就不多说了,不在本文讨论范围之内,下回分解。

三、闭合浮动的原理——了解 hasLayout 和 Block formatting contexts

先看一下清理浮动的各种方法

1、添加额外标签

通过在浮动元素末尾添加一个空的标签,其他标签br等亦可

<div class="wrap" id="float1">
    <h2>添加额外标签</h2>
    <div class="main left">.main{float:left;}</div>
    <div class="side left">.side{float:right;}</div>
    <div style="clear:both;"></div>
</div>
<div class="footer">.footer</div>

优雅的 Demo

  • 优点:通俗易懂,容易掌握

  • 缺点:可以想象通过此方法,会添加多少无意义的空标签,有违结构与表现的分离,在后期维护中将是噩梦,这是坚决不能忍受的,所以你看了这篇文章之后还是建议不要用了吧。

2、使用 br标签和其自身的 html属性

这个方法有些小众,br 有 clear=“all | left | right | none” 属性

<div class="wrap" id="float2">
    <h2>使用 br标签和其自身的 html属性</h2>
    <div class="main left">.main{float:left;}</div>
    <div class="side left">.side{float:right;}</div>
    <br clear="all" />
</div>
<div class="footer">.footer</div>

优雅的 Demo

  • 优点:比空标签方式语义稍强,代码量较少

  • 缺点:同样有违结构与表现的分离,不推荐使用

3、父元素设置 overflow:hidden

通过设置父元素overflow值设置为hidden;在IE6中还需要触发 hasLayout ,例如 zoom:1;

<div class="wrap" id="float3" style="overflow:hidden; *zoom:1;">
    <h2>父元素设置 overflow </h2>
    <div class="main left">.main{float:left;}</div>
    <div class="side left">.side{float:right;}</div>
</div>
<div class="footer">.footer</div>

优雅的 Demo

  • 优点:不存在结构和语义化问题,代码量极少

  • 缺点:内容增多时候容易造成不会自动换行导致内容被隐藏掉,无法显示需要溢出的元素;04年POPO就发现overflow:hidden会导致中键失效,这是我作为一个多标签浏览控所不能接受的。所以还是不要使用了

4、父元素设置 overflow:auto 属性

同样IE6需要触发hasLayout,演示和3差不多

  • 优点:不存在结构和语义化问题,代码量极少

  • 缺点:多个嵌套后,firefox某些情况会造成内容全选;IE中 mouseover 造成宽度改变时会出现最外层模块有滚动条等,firefox早期版本会无故产生focus等, 请看 嗷嗷的 Demo ,不要使用

5、父元素也设置浮动
  • 优点:不存在结构和语义化问题,代码量极少

  • 优点:使得与父元素相邻的元素的布局会受到影响,不可能一直浮动到body,不推荐使用

6、父元素设置display:table

**优雅的 Demo

  • 优点:结构语义化完全正确,代码量极少

  • 优点:盒模型属性已经改变,由此造成的一系列问题,得不偿失,不推荐使用

7、使用:after 伪元素

需要注意的是 :after是伪元素(Pseudo-Element),不是伪类(某些CSS手册里面称之为“伪对象”),很多闭合浮动大全之类的文章都称之为伪类,不过csser要严谨一点,这是一种态度。

由于IE6-7不支持:after,使用 zoom:1触发 hasLayout。

该方法源自于: How To Clear Floats Without Structural Markup

原文全部代码如下:

<style type="text/css">  
.clearfix:after {  
    content: "."; 
    display: block; 
    height: 0; 
    clear: both; 
    visibility: hidden;  
}   
.clearfix {
    display: inline-block;
} 
</style> 

/* for IE/Mac */   
<!--[if IE]> 
<style type="text/css"> 
.clearfix {
    zoom: 1;            /* triggers hasLayout */  
    display: block;     /* resets display for IE/Win */
} 
</style>  
<![endif]-->  

鉴于 IE/Mac的市场占有率极低,我们直接忽略掉,最后精简的代码如下:

.clearfix:after {
     content:"."; 
     display:block; 
     height:0; 
     visibility:hidden; 
     clear:both; 
}
.clearfix { 
    *zoom:1; 
}

**优雅的 Demo

  • 优点:结构和语义化完全正确,代码量居中

  • 优点:复用方式不当会造成代码量增加

原文结尾:

前前后后花了三天写完了这篇文章。如果觉得本文对您有帮助,您的留言就是对我最大的支持,同时由于精力有限,欢迎指出文中错误与不足,共勉之!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章