CSS float(float), a property that we both love and hate. Love it, because through floating, we can layout the layout very conveniently; hate it, there are too many problems left after floating that need to be solved, especially IE6-7 and below without special instructions refer to the IE browser of the windows platform
Float, a property we both love and hate. Love it, because through floating, we can layout the layout very conveniently; hate it, there are too many problems left after floating that need to be solved, especially IE6-7 (the following refers to the IE browser of the windows platform unless otherwise specified). Maybe many people have this question, where does the floating come from? Why does CSS clear floats? What is the principle of clearing floats? This article will analyze the secrets in depth step by step, making floating more convenient to use.
1. Clearing float or closing float (Enclosing float or Clearing float)?
Many people are accustomed to calling it clearing floats. I have always called it this before, but it is not accurate. We should treat the code with a rigorous attitude, which can also better help us understand the three questions at the beginning.
1) Clear float: The corresponding word for clear is clear, and the corresponding attribute in CSS is clear: left | right | both | none;
2) Close float: The more precise meaning is to close the floating element, so that Reduce the impact of floating.
Please see the elegant Demo for the difference between the two
Through the above examples, we found that in fact, the effect we want to achieve is to close the float, rather than simply clear the float. Set clear on the footer: both clear Floating does not solve the problem of warp height collapse.
Conclusion: Using closed float is more rigorous than clearing float, so we will call it closed float in the following article.
2. Why do we need to clear floats?
To answer this question, we must first talk about the positioning mechanism in CSS: ordinary flow, floating, absolute positioning (where "position:fixed" is a subclass of "position:absolute").
1) Ordinary flow: Many people or articles call it document flow or ordinary document flow. In fact, there is no such word in the standard. If the literal translation of document flow into English is document flow, there is only another word in the standard, called normal flow, or normal flow. But it seems that everyone is more accustomed to the name document flow, because this is how many Chinese-translated books come from. For example, in "CSS Mastery", the original English book only has the word "normal flow" from beginning to end, and document flow (document flow) has never appeared
2) Floating: The floating box can be left or right Move until its outer edge meets the edge of the containing box or another floated box. Floating boxes do not belong to the ordinary flow in the document. When an element is floated, it will not affect the layout of the block-level box but only the arrangement of inline boxes (usually text). The ordinary flow in the document will behave like Just like the floating box does not exist, when the height of the floating box exceeds the containing box, the containing box will not automatically stretch up to close the floating element ("height collapse" phenomenon). As the name suggests, it floats on ordinary currents, like floating clouds, but can only float left and right.
It is precisely because of the characteristics of floating that after the elements in the ordinary flow are floated, since there are no other ordinary flow elements inside the containing box, the height will be 0 (height collapse). In actual layout, this is often not what we want, so we need to close the floating element so that its containing box shows a normal height.
I won’t say much about absolute positioning. It is not within the scope of this article and will be broken down next time.
3. The principle of clearing floats - understanding hasLayout and Block formatting contexts
First look at the various methods of clearing floats: (The most comprehensive css clearfix to clear floats Method)
1) Add additional tags
This is a method that the teacher told us in school, by adding an empty tag at the end of the floating element such as
The code is as follows:
<p class="warp" id="float1"> <h2>1)添加额外标签</h2> <p class="main left">.main{float:left;}</p> <p class="side left">.side{float:right;}</p> <p style="clear:both;"></p> </p> <p class="footer">.footer</p>
Advantages: Easy to understand and easy to master
Disadvantages: You can imagine how many meaningless empty tags will be added through this method, which violates the structure and performance Separation will be a nightmare in later maintenance, which is absolutely intolerable, so after reading this article, it is recommended not to use it.
2) Use the br tag and its own html attribute
This method is somewhat niche, br has a clear="all | left | right | none" attribute
<p class="warp" id="float2"> <h2>2)使用 br标签和其自身的 html属性</h2> <p class="main left">.main{float:left;}</p> <p class="side left">.side{float:right;}</p> <br clear="all" /> </p> <p class="footer">.footer</p>
Elegant Demo
Advantages: Slightly stronger semantics than the empty tag method, less code volume
Disadvantages: It also violates the separation of structure and performance, and is not recommended.
3) Parent element setting overflow: hidden
Set the overflow value of the parent element to hidden; in IE6, hasLayout also needs to be triggered, such as zoom: 1;
The code is as follows:
<p class="warp" id="float3" style="overflow:hidden; *zoom:1;"> <h2>3)父元素设置 overflow </h2> <p class="main left">.main{float:left;}</p> <p class="side left">.side{float:right;}</p> </p> <p class="footer">.footer</p>
优点:不存在结构和语义化问题,代码量极少
缺点:内容增多时候容易造成不会自动换行导致内容被隐藏掉,无法显示需要溢出的元素;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;} /* for IE/Mac */ </style> <!--[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; }
优点:结构和语义化完全正确,代码量居中
缺点:复用方式不当会造成代码量增加
小结
通过对比,我们不难发现,其实以上列举的方法,无非有两类:
其一,通过在浮动元素的末尾添加一个空元素,设置 clear:both属性,after伪元素其实也是通过 content 在元素的后面生成了内容为一个点的块级元素;
其二,通过设置父元素 overflow 或者display:table 属性来闭合浮动,我们来探讨一下这里面的原理。
在CSS2.1里面有一个很重要的概念,但是国内的技术博客介绍到的比较少,那就是 Block formatting contexts (块级格式化上下文),以下简称 BFC。
CSS3里面对这个规范做了改动,称之为:flow root,并且对触发条件进行了进一步说明。
那么如何触发BFC呢?
float 除了none以外的值
overflow 除了visible 以外的值(hidden,auto,scroll )
display (table-cell,table-caption,inline-block)
position(absolute,fixed)
fieldset元素
需要注意的是,display:table 本身并不会创建BFC,但是它会产生匿名框(anonymous boxes),而匿名框中的display:table-cell可以创建新的BFC,换句话说,触发块级格式化上下文的是匿名框,而不是 display:table。所以通过display:table和display:table-cell创建的BFC效果是不一样的。
fieldset 元素在www.w3.org里目前没有任何有关这个触发行为的信息,直到HTML5标准里才出现。有些浏览器bugs(Webkit,Mozilla)提到过这个触发行为,但是没有任何官方声明。实际上,即使fieldset在大多数的浏览器上都能创建新的块级格式化上下文,开发者也不应该把这当做是理所当然的。CSS 2.1没有定义哪种属性适用于表单控件,也没有定义如何使用CSS来给它们添加样式。用户代理可能会给这些属性应用CSS属性,建议开发者们把这种支持当做实验性质的,更高版本的CSS可能会进一步规范这个。
BFC的特性:
1)块级格式化上下文会阻止外边距叠加
当两个相邻的块框在同一个块级格式化上下文中时,它们之间垂直方向的外边距会发生叠加。换句话说,如果这两个相邻的块框不属于同一个块级格式化上下文,那么它们的外边距就不会叠加。
2)块级格式化上下文不会重叠浮动元素
根据规定,一个块级格式化上下文的边框不能和它里面的元素的外边距重叠。这就意味着浏览器将会给块级格式化上下文创建隐式的外边距来阻止它和浮动元素的外边距叠加。由于这个原因,当给一个挨着浮动的块级格式化上下文添加负的外边距时将会不起作用(Webkit和IE6在这点上有一个问题——可以看这个测试用例)。
3)块级格式化上下文通常可以包含浮动
详见: W3C CSS2.1 - 10.6.7 'Auto' heights for block formatting context roots
通俗地来说:创建了 BFC的元素就是一个独立的盒子,里面的子元素不会在布局上影响外面的元素,反之亦然,同时BFC任然属于文档中的普通流。
至此,您或许明白了为什么 overflow:hidden或者auto可以闭合浮动了,真是因为父元素创建了新的BFC。对于张鑫旭在对《overflow与zoom”清除浮动”的一些认识 》一文中对于用包裹来解释闭合浮动的原理,我觉得是不够严谨的,而且没有依据。并且说道“Firefox等浏览器并没有haslayout的概念”,那么现代浏览器是有BFC的,从表现上来说,hasLayout 可以等同于 BFC。
IE6-7的显示引擎使用的是一个称为布局(layout)的内部概念,由于这个显示引擎自身存在很多的缺陷,直接导致了IE6-7的很多显示 bug。当我们说一个元素“得到 layout”,或者说一个元素“拥有 layout” 的时候,我们的意思是指它的微软专有属性 hasLayout http://www.php.cn/ ... rties/haslayout.asp 为此被设为了 true 。IE6-7使用布局的概念来控制元素的尺寸和定位,那些拥有布局(have layout)的元素负责本身及其子元素的尺寸设置和定位。如果一个元素的 hasLayout 为false,那么它的尺寸和位置由最近拥有布局的祖先元素控制。
触发hasLayout的条件:
position: absolute
float: left|right
display: inline-block
width: 除 “auto” 外的任意值
height: 除 “auto” 外的任意值 (例如很多人清除浮动会用到 height: 1% )
zoom: 除 “normal” 外的任意值 (MSDN) http://www.php.cn/ ... properties/zoom.asp
writing-mode: tb-rl (MSDN) http://www.php.cn/ ... ies/writingmode.asp
在 IE7 中,overflow 也变成了一个 layout 触发器:
overflow: hidden|scroll|auto ( 这个属性在IE之前版本中没有触发 layout 的功能。 )
overflow-x|-y: hidden|scroll|auto (CSS3 盒模型中的属性,尚未得到浏览器的广泛支持。他们在之前IE版本中同样没有触发 layout 的功能)
hasLayout更详细的解释请参见 old9翻译的 大名鼎鼎的 《On having layout》一文(英文原文:http://www.php.cn/),由于old9博客被墙,中文版地址:
IE8使用了全新的显示引擎,据称不使用 hasLayout属性了,因此解决了很多深恶痛绝的bug。
综上所述:
在支持BFC的浏览器(IE8+,firefox,chrome,safari)通过创建新的BFC闭合浮动;
在不支持 BFC的浏览器 (IE6-7),通过触发 hasLayout 闭合浮动。
四、闭合浮动方法——精益求精
上面已经列举了7种闭合浮动的方法,通过第三节分析的原理,我们发现其实更多的:display:table- cell,display:inline-block等只要触发了BFC的属性值都可以闭合浮动。从各个方面比较,after伪元素闭合浮动无疑是相对比较好的解决方案了,下面详细说说该方法。
代码如下:
.clearfix:after {content:"."; display:block; height:0; visibility:hidden; clear:both; } .clearfix { *zoom:1; }
1) display:block 使生成的元素以块级元素显示,占满剩余空间;
2) height:0 避免生成内容破坏原有布局的高度。
3) visibility:hidden 使生成的内容不可见,并允许可能被生成内容盖住的内容可以进行点击和交互;
4)通过 content:"."生成内容作为最后一个元素,至于content里面是点还是其他都是可以的,例如oocss里面就有经典的 content:"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",有些版本可能content 里面内容为空,一丝冰凉是不推荐这样做的,firefox直到7.0 content:”" 仍然会产生额外的空隙;
5)zoom:1 触发IE hasLayout。
通过分析发现,除了clear:both用来清除浮动的,其他代码无非都是为了隐藏掉content生成的内容,这也就是其他版本的闭合浮动为什么会有font-size:0,line-height:0。
精益求精方案一:
相对于空标签闭合浮动的方法代码似乎还是有些冗余,通过查询发现Unicode字符里有一个“零宽度空格”,也就是U+200B ,这个字符本身是不可见的,所以我们完全可以省略掉 visibility:hidden了 代码如下:
.clearfix:after {content:"\200B"; display:block; height:0; clear:both; }
.clearfix { *zoom:1; }.
精益求精方案二:
由Nicolas Gallagher 大湿提出来的,原文:A new micro clearfix hack,该方法也不存在firefox中空隙的问题。
代码如下:
/* For modern browsers */ .cf:before,.cf:after { content:""; display:table; } .cf:after { clear:both; }/* For IE 6/7 (trigger hasLayout) */ .cf { zoom:1; }
需要注意的是:
上面的方法用到了 :before伪元素,很多人对这个有些迷惑,到底我什么时候需要用before呢?为什么方案一没有呢?其实它是用来处理margin边距重叠的,由于内部元素 float 创建了BFC,导致内部元素的margin-top和 上一个盒子的margin-bottom 发生叠加。如果这不是你所希望的,那么就可以加上before,如果只是单纯的闭合浮动,after就够了!并不是如同大漠《Clear Float》一文所说的:但只使用clearfix:after时在跨浏览器兼容问题会存在一个垂直边距叠加的bug,这不是bug,是BFC应该有的特性。
在实际开发中,改进方案一由于存在Unicode字符不适合内嵌CSS的GB2312编码的页面,使用方案7完全可以解决我们的需求了,改进方案二等待大家的进一步实践。方案3、4通过overflow闭合浮动,实际上已经创建了新的 块级格式化上下文,这将导致其布局和相对于浮动的行为等发生一系列的变化,清除浮动只不过是一系列变化中的一个作用而已。所以为了闭合浮动去改变全局特性,这是不明智的,带来的风险就是一系列的bug,比如firefox 早期版本产生 focus,截断绝对定位的层等等。始终要明白,如果单单只是需要闭合浮动,overflow就不要使用,而不是某些文章所说的“慎用”。
前前后后花了三天写完了这篇css为什么要清除浮动? 清除浮动的原理的文章。如果觉得本文对您有帮助,您的留言就是对我最大的支持,同时由于精力有限,欢迎指出文中错误与不足,共勉之!