(译)元素浮动的那些事儿
原文:http://bitsofco.de/2015/how-floating-works/,作者 Ire Aderinokun 发表于 2015 年 8 月 11 日。
尽管我们现在用浮动布局已经很少了,但是在一些特殊的需求下,它仍然是唯一可行的解决方案。在这些少见的需求中,浮动元素真正的表现形式并非像我想的那样,这使我倍受挫败。所以我决定研究一下浮动行为的规则,从而可以适当地去使用它。
浮动的规则
float属性总共可以设置四种值:
.foo { float: left | right | inherit | none }
下面这些规则定义了某元素设置为以上几种浮动值时,分别该如何在其父元素乃至文档中进行定位。
1. 浮动元素对于其父元素“不可见”。
实际上,浮动元素会脱离其父元素。如果一个父元素仅包裹一个浮动的子元素,它会像空元素那样没有任何高度。这与其只包裹着一个绝对定位元素时的表现是非常类似的。
.parent { position: relative; padding: 10px; } .child { float: left }
2. 向左/右浮动的元素,总是会尽可能地向其父元素的顶部及左/右部靠拢。
一个向左或向右浮动的元素总是会想办法占据这个“最佳”位置。
3. 如果浮动元素之前定义了一个兄弟元素,那么浮动元素会换行显示。
尽管浮动元素会尽可能地靠近父元素的顶部,但是如果有任意的非浮动的兄弟元素位于其之前,浮动元素便会被挤下去。无论这个兄弟元素是行内元素还是块元素。这就意味着如果我们定义一个浮动元素位于一个段落之前和之后,得到的结果是完全不同的。
浮动元素位于段落元素之前
浮动元素位于段落元素之后
一个小学生注:作者的这种说法并不严谨。她仅验证了段落时的情况。而真实情况是这样的:
如果浮动元素位于非浮动元素之前 |
||
非浮动元素的类型 |
浏览器类型 |
结果 |
块级元素 |
IE8、8+、chrome等现代浏览器 |
永不换行 |
块级元素 |
IE7 - |
不换行,但当快级元素被显性设置宽度且宽度足够大,父容器不足以在同行排列其与浮动元素时,其会换行位于浮动元素之下。 |
行内级元素 |
IE8、8+、chrome等现代浏览器 |
永不换行 |
行内级元素 |
IE7 - |
永不换行 |
如果浮动元素位于非浮动元素之后 |
||
非浮动元素的类型 |
浏览器类型 |
结果 |
块级元素 |
IE8、8+、chrome等现代浏览器 |
永远换行 |
块级元素 |
IE7 - |
永远换行 |
行内级元素 |
IE8、8+、chrome等现代浏览器 |
不换行,但当父容器宽度不足以在同行排列两者时,会换行。 |
行内级元素 |
IE7 - |
永远换行 |
如果你想亲自实验一下,猛戳这个测试地址。
经常有人会遇到浮动元素在IE6下换行的bug,根据上面的规则,只要把浮动元素放置在非浮动元素的前面,这个bug自然会迎刃而解了。
4. 预先定义的浮动元素可以享受到更佳的位置。
在HTML标签中,越靠前的浮动元素越能享受规则2中提到的“最佳”位置。例如,假如现在有一些向右浮动的元素,按照HTML中定义的顺序,第一个元素会呈现在最右侧,因为最右侧是离父元素最近的,是“最佳”位置。
<div class="container"> <div class="right">1</div> <div class="right">2</div> <div class="right">3</div> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p> </div>
5. 相对于尽可能地靠近父元素的左侧和右侧,浮动元素更倾向于靠近其顶部。
当同一个方向(左/右)有多个浮动元素时,靠后者会选择远离父元素左/右侧,从而尽可能地接近父元素的顶部。这意味着多个相邻的浮动元素会尽可能地一个挨一个地排成一行展示,仅当父元素的宽度不足以包裹它们时,后定义的浮动元素才会被挤下去。
在这个例子中,相比于元素3,元素2取得了更佳的位置。
6. 浮动元素不应溢出其父元素。
一个向左浮动的元素不可以超出其父元素的左侧边。
一个向左浮动的元素不应该超出父元素的右侧边,除非父元素实在没有位置容纳下它。
浮动的清除
clear属性常常伴随着float属性而存在。它使我们可以打破浮动元素为文档流带来的变化。我们可以把它设置为以下三个值:
.foo { clear: left | right | both }
当一个元素拥有clear:left属性时,这意味着这个元素必须位于向左浮动的元素之下。如果一个元素的clear属性为both时,它必须位于任意浮动元素之下。
如果一个元素仅仅清楚了左侧或右侧的浮动,那么向另一侧浮动的元素不会受此影响。
<div class="container"> <div class="left">1</div> <div class="left">2</div> <div class="left">3</div> <div class="right">1</div> <div class="right">2</div> <div class="right">3</div> <p class="clear-left">Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p> </div>
Clearfix
我们常常对如何合适地清楚浮动有很多困惑,特别是应付那些古老的浏览器时。我用过的一个非常流行的清除浮动的方法是CSS Mojo中写的,他将下面的样式赋予浮动元素的父元素或者任意在它之后定义的元素:
.cf::after { content:""; display:table; clear:both; }
至于为什么这样来使用这些样式,你可以从这篇博客中找到答案。从本质上来说,这个方法也是通过创建了一个不可见的伪元素来达到清除浮动的目的。
一个小学生注:我们之前一直用的clearfix是这样的:
.clearfix:after { content: "."; clear: both; visibility: hidden; display: block; height: 0; } .clearfix{ *zoom:1}
由于IE7及以下浏览器是不支持display:table的,相比于上面作者提到的方式,虽然要多写几行样式。但胜在支持IE8-。在国内还是老老实实用这个clearfix比较好。
更多清除浮动的方法可以查看这个demo:清除浮动的7种方法
注意:上面的.clearfix:after一定要用单冒号,CSS3建议我们对伪元素使用双冒号,与伪类加以区分。现代浏览器识别两种写法,但是IE8仅识别单冒号。如果你写的是双冒号“.clearfix::after”,由于"*zoom:1"IE8也无法识别,这会导致你的clearfix在IE8中无效。
(全文完)