李东的技术博客

文章内容Content

float“浮动”的小毛病

2016/08/01 363 ℃ 抢个沙发

by LiDong from https://www.lidongtech.com/not-understand-floating.html
本文可全文转载,但需得到原作者书面许可,同时保留原作者和出处。如果只是引流,请随意~

文章目录

啰嗦的开头

不知道吃坏肚子了还是肚子着凉了,最近“屁”一直不断。在办公室也是一个连着一个,只有男生在的时候就肆无忌惮的“砰砰”的响,如果有女孩子在场就只能强行的憋着,实在是憋不住了就一点一点的把P给挤出来,尽量不发出任何声音。

最后同事调侃我说,如果再这么下去。我就能不借助任何工具,而只是靠自己就能浮起来了——就像日本传说中的河童一样。不光能体验飞行的感觉,连停车位都给省了,还不怕堵车。效果挺好但是真的是很尴尬啊!再这么下去连翔都喷出来了。病急乱投医啊,最后吃了几片自己也搞不清楚的药片之后,终于不再尴尬了-。-!

浮动的简介

能让人“浮”起来的p真的很难搞啊!太尴尬了……不过在前端工作中,也有“浮动”着且很难搞的东西——就是属性float。这货的作用很简单就是定义元素浮动到左侧还是右侧。别看它作用描述只有短短的几个字,但是它的威力却一点也不小。在网页制作中,布局控制就是依靠三种手段。

  1. float:浮动。
  2. position:定位。
  3. 文本流。

定位position和文本流不再说明了,主要说下浮动float,在最开始的设计初衷中,float是服务于排版的,对~你没看错就是文字排版的那个排版。这个没啥好惊讶的,因为CSS的设计初衷就是排版。而布局功能只是一种另类的应用。在图片上设置float能让文字环绕图片排列,就好像文字内容像水流一样遇见了一块石头然后绕了过去,这样达到图文混排的效果,能让文章更加美观。后来网页制作者发现所有的元素都能通过CSS来设置浮动,于是float属性就用来布局了,效果还很好~谁用谁知道。

虽然浮动使用起来很好用,但是会产生一些很意外的结果。我至今还记得当时我刚刚接触Div+Css的时候的糗事,因为浮动没有控制好,整个页面被我搞的就像小时候玩的“尿泥”一样一团糟。主要原因当时我对float的概念和特点不是十分清晰。

想要将float运用自如,那么必须先理解它的几个特点,也是很有趣的特点。

  1. 任何元素都可以浮动。
  2. 浮动之后的元素会脱离正常的文本流(flow)
  3. 浮动元素会生成一个块级元素,而不论它本身是何种元素。
  4. 浮动元素的外边距margin不会与相邻的元素的margin产生折叠。(margin collapse)
  5. 元素对象设置了float属性之后,它将不再独自占据一行。
  6. 浮动块可以向左或向右移动,直到它的外边缘碰到包含它的框或另一个浮动块的边框为止。
  7. 内容元素会沿着浮动元素的一侧“流动”。(内容元素没有设置clear属性的情况下)

所有的主流浏览器都是支持float的,它能设置的值是四种:LeftRight分别浮动元素到各自的方向,None(默认的)使元素不浮动,Inherit将会从父级元素获取float值。note:关于margin collapse(margin折叠)的问题可以出门右转>>>>>>《浅析让人蛋疼的margin折叠》

浮动的应用

因为float的种种特点,让它在“布局”中获得了很高的地位。很多网页整体的排版也是利用浮动属性让大块的元素“飞起来”实现的。例如下图所示,就是在全局使用浮动来进行网页布局。

利用Float浮动进行网页布局

利用Float浮动进行网页布局

除了在整体上使用float布局之外,在一些“细节”上也可以用浮动实现一些功能,例如在没有设置任何CSS规则的时候,一个无序列表<ul>中的<li>会成纵向排列。这是因为它的默认display:list-item的缘故。如果我们想让<li>成横向排列的话,这时候我们有两种方法,一种是设置display,另外一种就是设置float。除了让元素横向排列之外,还能用浮动实现文字围绕图片做图文混排,这个功能才是设计这个属性的初衷。两种情况的设置及图文混排实例demo如下:

See the Pen float,display,default by tkoctkoc (@tkoctkoc) on CodePen.27881

这里值得一提的是,在一些“功能性的表现”上浮动float能做的,使用定位position也可以实现。我们通过给父元素设置相对定位position:relative;,将子元素设置绝对定位position:absolute;的方式,再配合top/right/bottom/left来让元素“移动”,同样也能达到浮动的效果。虽然浮动float和定位position所能实现的功能很近似,但是它们之间还是有一些区别的,具体区别如下图:

浮动float和定位position的区别

浮动float和定位position的区别

浮动的毛病

根据W3C的文档说明,浮动的元素会脱离文本流。下面引用原文以及我个人蹩脚的翻译。

Since a float is not in the flow, non-positioned block boxes created before and after the float box flow vertically as if the float did not exist. However, the current and subsequent line boxes created next to the float are shortened as necessary to make room for the margin box of the float.

A line box is next to a float when there exists a vertical position that satisfies all of these four conditions: (a) at or below the top of the line box, (b) at or above the bottom of the line box, (c) below the top margin edge of the float, and (d) above the bottom margin edge of the float.

Note: this means that floats with zero outer height or negative outer height do not shorten line boxes.

主要看第一句:由于浮动不在流中,所以浮动框之前和之后创建的非定位块框垂直流向,就像浮点数不存在一样。

这个就是著名的float高度塌陷,哎~往事不堪回首啊,我就在这上面栽过跟头。多愁善感对于我们的进步是没有帮助的,我们要探究知识本源,那么就需要解读上面的文字,可是这段话看起来不像是“人话”看不明白,没关系大概说明下可能你就会恍然大悟,也许你也遇见过这种问题。

浮动高度塌陷的意思就是说如果父元素只包含浮动元素,且父元素本身height:auto、没有设置或是设置了负值。那么父元素的高度就会塌缩为零。如果父元素不包含任何的可见背景图片或者背景颜色,那么这个问题会很难被注意到,同时问题也会变得无所谓。但是如果父元素包含背景图片或背景色的话,这个问题就会变得无比重要,因为高度坍塌导致父元素高度为零,父元素的背景图片或背景色会完全显示不出来。以至于在父元素下方的相邻元素会“跑上来”,这样就会影响到整体网页的布局。

如下图,父元素没有设置高度只是设置了颜色和边框,当它内部的子元素全部浮动的时候,整个父元素的高度全部没有了。小tips:父元素内部没有浮动或一部分浮动的时候,父元素的高度是依靠子元素的高度给“撑”起来的。

子元素浮动后父元素height-collapse

子元素浮动后父元素height-collapse

防止这种情况发生所采用的技术叫做清除浮动。清除浮动的方法有好几种,这篇文章不做过多的累述。本人比较推荐使用的就是利用伪元素清除浮动,具体办法查看文章《好用的伪元素:before和:after》

由于浮动的元素会脱离文本流,所以浮动元素相对于流中的其他非浮动元素块表现得像不存在一样。假设容器内部有三个块级元素,我们分别给它们设置了宽度、高度、边框及背景色。在木有浮动的存在的时候如下图:

如果我们将div#id-1设置float:right;,那么它就会向右浮动,直到自己的右边缘遇见容器的右边缘。

这种情况下比较重点的是div#id-1设置float:left;div#id-1脱离文档流并且向左移动,直到它的左边缘碰到容器的左边缘;分歧出现在这里,在IE8+、Firefox和chrome中因为它不再处于文档流中,所以它不占据空间,实际上覆盖住了div#id-2,使div#id-2从视觉效果中消失。div#id-2的内容却继续在原位置上显示。而IE6和IE7中紧跟在浮动元素的div#id-2也会跟着浮动。

float属性在不同IE的版本显示的效果有所不同,比较著名的就是在IE6下面浮动的双边距BUG。这个BUG的产生方式是:一个居左浮动(float:left)的元素放置进一个容器盒(box),并在浮动元素上使用了左边界(margin-left) 在ie6内便产生双倍边距。这个Bug仅当浮动边界和浮动元素的方向相同时出现在浮动元素和容器盒的内边缘之间,在这之后的任意有着相似边界的浮动元素不会呈现双倍边界。只有特定的浮动行的第一个浮动元素会遭遇这个Bug。像居左的情况一样,双倍边界同样神秘地显示在居右的相同方式。解决方法:IE6双边距的方法就是使用display:inline;忽略浮动。

在IE6下面还有一个神秘的文本3像素BUG,这个BUG是指IE6中临近着浮动元素的文本会神奇的被踢出去3像素,好像浮动元素的周围有一个奇怪的力场一样。关于这个BUG太著名了网上一搜相关文章一大把,不累述了。上图说话,这图也是扣人家的……

解决方法:解决IE6下3像素BUG的方式主流与两种,一种是补丁,另一种是双浮动。补丁法就是要么元素给自己浮动方向的反方向设置一个负值的margin。要么就是在临近元素设置浮动同方向的负值margin。双浮动就是直接把临近元素也给设置一个浮动。

好吧~看到这里你觉得在IE6下面浮动简直就是一个折磨我们大前端工程师的一个恶魔。不过要是你以为到这里就结束了,那么你就太天真了。什么?还有?不会吧,知道真相的我眼泪掉下来……

下面这一个BUG不光在IE6下面出现,在IE7下面也会显露它“邪恶”的身影。这就是就是另外一个重要的IE6/IE7父子元素双浮动底边距BUG这个BUG的出现情况是父元素浮动,它内部也有浮动子元素,那么这些子元素的底边距会被父元素忽略掉。

解决方法:父元素底部bottom使用padding。这个方法的缺点是不能换行,如果想要换行的话,那就必须将浮动父元素的浮动子元素设置padding值了。

文章的最后

浮动元素对于初学者来说,确实很难驾驭。这个难驾驭是指在css hack方面。而且在使用浮动的时候,一定要切忌给浮动的父元素的最后设置清除浮动。其实这个东西弄明白之后还是很简单的。也没有什么过多的要说的了。那就88……还有,以后吃东西要注意不能吃坏了肚子了,不然就真的成日本的河童了。

(报告完毕!)
本文标签:标签:, , ,