CSS float 는 우리 모두가 좋아하고 싫어하는 속성입니다. 플로팅을 통해 레이아웃을 매우 편리하게 배치할 수 있기 때문에 마음에 듭니다. 플로팅 후에는 해결해야 할 문제가 너무 많습니다. 특히 특별한 지침이 없는 IE6-7 이하에서는 Windows 플랫폼의 IE 브라우저를 참조하세요. .
플로트(Float)는 우리 모두가 사랑하고 싫어하는 속성입니다. 플로팅을 통해 레이아웃을 매우 편리하게 레이아웃할 수 있기 때문에 마음에 듭니다. 플로팅 후에는 해결해야 할 문제가 너무 많습니다. 특히 IE6-7(다음은 달리 언급하지 않는 한 Windows 플랫폼의 IE 브라우저를 나타냅니다.) 지정). 아마 많은 사람들이 이런 질문을 할 것입니다. 부유물은 어디서 오는 걸까요? CSS 클리어가 부동하는 이유는 무엇입니까? 수레 청소의 원리는 무엇입니까? 이 글에서는 비밀을 단계별로 심층적으로 분석하여 플로팅을 더욱 편리하게 사용할 수 있도록 하겠습니다.
1. 플로트 지우기 또는 플로트 닫기(Enclosing float 또는 Clearing float)?
많은 사람들이 이를 클리어 플로트(clearing floats)라고 부르는 데 익숙합니다. 저는 예전에도 그렇게 불렀지만 정확하지는 않습니다. 우리는 엄격한 태도로 코드를 다루어야 하며, 이는 처음에 세 가지 질문을 더 잘 이해하는 데 도움이 될 수도 있습니다.
1) 클리어 플로트(Clear float): 클리어에 해당하는 단어는 클리어이며, CSS의 해당 속성은 클리어입니다. 왼쪽 | 없음 오른쪽 | 요소, 따라서 부동의 영향을 줄입니다.
두 가지의 차이점은 우아한 데모를 참조하세요.
위의 예를 통해 우리가 달성하려는 효과는 단순히 플로트를 지우는 것보다 플로트를 닫는 것임을 알 수 있습니다. 바닥글: 둘 다 클리어 플로팅은 워프 높이 붕괴 문제를 해결하지 못합니다.
결론: 닫힌 플로트를 사용하는 것은 플로트를 지우는 것보다 더 엄격하므로 다음 기사에서는 이를 닫힌 플로트라고 부르겠습니다.
2. 플로트를 제거해야 하는 이유는 무엇인가요? 이 질문에 대답하려면 먼저 CSS의 위치 지정 메커니즘인 일반 흐름, 부동, 절대 위치 지정(여기서 "위치:고정"은 "위치:절대"의 하위 클래스임)에 대해 이야기해야 합니다.
1) 일반 흐름: 많은 사람들이나 기사에서 이를 문서 흐름 또는 일반 문서 흐름이라고 부릅니다. 실제로 표준에는 그런 단어가 전혀 없습니다. 문서 흐름을 영어로 문자 그대로 번역하면 문서 흐름(document flow)이라는 표준에는 정상 흐름(normal flow) 또는 정상 흐름(normal flow)이라는 또 다른 단어만 있습니다. 하지만 이름 문서 흐름에 모두가 더 익숙해진 것 같습니다. 중국어로 번역된 책이 이렇기 때문입니다. 예를 들어 "CSS Mastery"의 경우 원본 영어 책에는 처음부터 끝까지 "normal flow"라는 단어만 있고 문서 흐름은 나타나지 않습니다.
2) 플로팅: 플로팅 상자는 왼쪽이나 오른쪽으로 이동할 수 있습니다. 외부 가장자리는 포함 상자 또는 다른 부동 상자의 가장자리와 만납니다. 플로팅 상자는 문서의 일반 흐름에 속하지 않습니다. 요소가 플로팅되면 블록 수준 상자의 레이아웃에는 영향을 미치지 않고 문서의 일반 흐름에는 인라인 상자 배열에만 영향을 미칩니다. 부동 상자가 존재하지 않는 것과 마찬가지로 부동 상자의 높이가 포함 상자를 초과하면 포함 상자가 부동 요소를 닫기 위해 자동으로 늘어나지 않습니다("높이 붕괴" 현상). 이름에서 알 수 있듯이 떠다니는 구름처럼 일반적인 흐름에 떠 있지만 왼쪽과 오른쪽으로만 떠다닐 수 있습니다.
정확한 플로팅의 특성 때문에 일반 흐름의 요소가 플로팅된 후 포함 상자 내부에 다른 일반 흐름 요소가 없기 때문에 높이가 0(높이 붕괴)이 됩니다. 실제 레이아웃에서는 이것이 우리가 원하는 것이 아닌 경우가 많으므로 포함 상자가 일반 높이를 표시하도록 부동 요소를 닫아야 합니다.
절대 위치 지정에 대해서는 많이 말하지 않겠습니다. 이는 이 기사의 범위에 포함되지 않으며 다음 번에 자세히 설명하겠습니다.
3. 부동 소수점 지우기 원리 - hasLayout 및 블록 형식 지정 컨텍스트 이해 먼저 부동 소수점을 지우는 다양한 방법을 살펴보세요. (
수레 부동 소수점을 지우는 가장 포괄적인 CSS Clearfix 방법)1) 추가 태그 추가
학교에서 선생님이 알려주신 방법인데, 플로팅 요소 끝에
<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>
단점: 이 방법을 사용하면 의미 없는 빈 태그가 얼마나 많이 추가될지 상상할 수 있습니다. 구조 및 성능 분리는 추후 유지보수 시 악몽이 될 수 있어 절대 용납할 수 없으므로 이 글을 읽은 후에는 사용하지 않는 것이 좋습니다.
2) br 태그와 자체 html 속성 사용
이 방법은 다소 틈새적입니다. br에는
<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>
우아한 데모
장점: 빈 태그 방식보다 약간 더 강력한 의미, 적은 코드량
단점: 구조와 성능의 분리도 위반하므로 권장하지 않습니다.
3) 상위 요소 settingsoverflow:hidden
은 IE6에서 상위 요소의 오버플로 값을 설정하여 숨김으로 설정됩니다. 다음:
<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 //m.sbmmt.com/ ... 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) //m.sbmmt.com/ ... properties/zoom.asp
writing-mode: tb-rl (MSDN) //m.sbmmt.com/ ... 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》一文(英文原文://m.sbmmt.com/),由于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为什么要清除浮动? 清除浮动的原理的文章。如果觉得本文对您有帮助,您的留言就是对我最大的支持,同时由于精力有限,欢迎指出文中错误与不足,共勉之!