css浮动现象及清除浮动的方法
首先先明确浮动最初的定义及使用场景:实现文本环绕图片的效果。
除了用浮动外,目前暂无其他方法实现文本环绕
再来看看浮动的具体定义:
浮动的框可以左右移动,直至它的外边缘遇到包含框或者另一个浮动框的边缘。浮动框不属于文档中的普通流,属于浮动布局。 (CSS三种基本的定位机制:普通流、浮动和绝对定位)
当一个元素浮动之后,不会影响到块级框的布局而只会影响内联框(通常是文本)的排列,文档中的普通流就会表现得和浮动框不存在一样,当浮动框高度超出包含框的时候,也就会出现包含框不会自动伸高来闭合浮动元素(“高度塌陷”现象)。顾名思义,就是漂浮于普通流之上,像浮云一样,但是只能左右浮动。
正是因为浮动的这种特性,导致本属于普通流中的元素浮动之后,包含框内部由于不存在其他普通流元素了,也就表现出高度为0(高度塌陷)。在实际布局中,往往这并不是我们所希望的,所以需要闭合浮动元素,使其包含框表现出正常的高度。
浮动未清除,会造成页面混乱(如下):
- 浮动元素没有设置宽度值,元素的宽度随内容的宽度的变化而变化
- 会对相邻的元素产生影响,相邻元素特指紧邻后面的元素。
如果相邻元素是块级元素会无视这个浮动的块框,也就是我们平时看到的效果——使到自身尽可能与这个浮动元素处于同一行,导致被浮动元素覆盖。除非这些 div 设置了宽度,并且父元素的宽度不足以包含它们,这样兄弟元素才会被强制换行。如果相邻元素是内联元素,则会尽可能围绕浮动元素。
- 元素父元素中的元素全部设置了浮动,父元素获取高度失效(父元素不计算浮动元素高度,即高度塌陷)。
在介绍清除浮动方法之前,先了解下:什么是BFC?
Block formatting contexts (块级格式化上下文),以下简称 BFC,用于对块级元素排版。创建了 BFC的元素就是一个独立的盒子(HTML中的一个盒子, 看不见而已),里面的子元素不会在布局上影响外面的元素,同样,外面的元素,也不会影响其子元素。
默认情况下只有根元素(body)一个块级上下文,其他元素满足至少下列条件之一才能形成BFC:
float属性不为none position属性不为static | relative display属性为下列之一:table-cell | table-caption| inline-block | flex | inline-flex overflow属性不为visible fieldset元素 //fieldset标签将表单的信息进行分类
但是它们各自却有着不一样的表现: display: table : 在响应式布局中会有问题 overflow: scroll : 可能会出现你不想要的滚动条 float: left: 使元素左浮动,并且其他元素对其环绕 overflow: hidden: 消除溢出部分
需要注意的是,display:table 本身并不会创建BFC,但是它会产生匿名框(anonymous boxes),而匿名框中的display:table-cell可以创建新的BFC,换句话说,触发块级格式化上下文的是匿名框,而不是display:table。所以通过display:table和display:table-cell创建的BFC效果是不一样的。
BFC的三个特性:
- BFC会阻止外边距叠加
当两个相邻的块框在同一个块级格式化上下文中时,它们之间垂直方向的外边距会发生叠加。换句话说,如果这两个相邻的块框不属于同一个块级格式化上下文,那么它们的外边距就不会叠加。
- BFC不会重叠浮动元素
根据规定,一个块级格式化上下文的边框不能和它里面的元素的外边距重叠。这就意味着浏览器将会给块级格式化上下文创建隐式的外边距来阻止它和浮动元素的外边距叠加。由于这个原因,当给一个挨着浮动的块级格式化上下文添加负的外边距时将会不起作用
- BFC通常可以包含浮动 (即计算BFC的高度时,浮动元素也参与计算)
独立的块级上下文可以包裹浮动流,全部浮动子元素也不会引起容器高度塌陷,也就是说包含块会把浮动元素的高度也计算在内,所以不用清除浮动来撑起高度。同时BFC任然属于文档中的普通流。
父元素创建了新的BFC,可以闭合浮动
还有一个跟浮动和BFC有关的概念:hasLayout
hasLayout是ie私有的概念,ie7及更低版本的ie浏览器不支持BFC,但我们可以针对ie7、6浏览器加入对应的hasLayout规则来实现BFC的效果!
IE使用Layout概念来控制元素的尺寸和位置。可以用Javascript函数hasLayout查看一个元素是否拥有Layout,返回true | false。如果一个元素有Layout,它就有自身的尺寸和位置;如果没有,它的尺寸和位置由最近的拥有布局的祖先元素控制。
hasLayout是一个只读属性,所以无法使用Javascript进行设置。元素的hasLayout属性值为true的时候会达到和BFC类似的效果。以下方法可以使元素hasLayout为true:
position: absolute float: left | right display: inline-block width: 除 “auto” 外的任意值 height: 除 “auto” 外的任意值 zoom: 除 “normal” 外的任意值 writing-mode: tb-rl 在IE7中使用overflow: hidden|scroll|auto
具体清除浮动的方法及其优缺点:
其实大家习惯称为“清除浮动”实际上应该称作“闭合浮动”。我们想要达到的效果确切的说是闭合浮动,而不是单纯的清除浮动,单纯的清除浮动,并不能解决容器高度塌陷的问题。(浮动清除前后效果如图:)
- 清除浮动:清除对应的单词是 clear,对应CSS中的属性是 clear:left | right | both |none;
- 闭合浮动:更确切的含义是使浮动元素闭合,从而减少浮动带来的影响。
总结来说,有两种方法闭合浮动:
浮动元素后面的同级标签加clear: both | left | right属性 (如下方法中的一、二、三)
为元素新建BFC(如下方法中的四、五、六)
<style type="text/css"> .clearFloatDiv1 { width: 400px; border: 1px solid #00ffde;padding: 20px; } .clearFloatDiv1 > div { width: 200px;padding: 25px 0; } .clearFloatDiv1 > div:nth-child(1) { background: #0ef; } .clearFloatDiv1 > div:nth-child(2) { background:#f7633d;} .clearFloatDiv1 > p { width: 400px; padding: 15px 0;background: #fcebd1; } </style> <div class="clearFloatDiv1"> <div style="float: left;"></div> //浮动元素 <div style="float: left;"></div> //浮动元素 </div>
方法一:浮动元素后,加样式含clear:both的空标签
<div class="clearFloatDiv1"> <div style="float: left;"></div> //浮动元素 <div style="float: left;"></div> //浮动元素 <p style="clear:both;"></p> //加空标签,闭合浮动 </div>
优点:通俗易懂,容易掌握
缺点:将添加很多无意义的空标签,有违结构与表现的分离,后期维护会是噩梦。
方法二(摧荐): 据说是最高大上的方法 :after 方法(注意:作用于浮动元素的父亲)
原理:一种清除浮动,他就是利用:after和:before来在元素内部插入两个伪元素,在伪元素中加入clear:both属性。与方法一类似
.clearFloat { /*对IE6/7的兼容处理*/ zoom:1; /*触发 hasLayout*/ } .clearFloat::after { clear:both; /*指清除所有浮动*/ content:'.'; /*内容,可以为空。也可以用Unicode字符里的 “零宽度空格”,也就是U+200B,这个字符本身是不可见的,可以省略掉 visibility:hidden*/ display:block; /*对于FF/chrome/opera/IE8不能缺少*/ width: 0; height: 0; visibility:hidden; /*允许浏览器渲染它,但是不显示出来*/ } <div class="clearFloatDiv1 **clearFloat** "> //加clearFloat清除浮动 <div style="float: left;"></div> //浮动元素 <div style="float: left;"></div> //浮动元素 </div>
优点:浏览器支持好,不容易出现怪问题(目前:大型网站都有使用,如:腾迅,网易,新浪等等)
缺点:代码多,要两句代码结合使用,才能让主流浏览器都支持
方法三(差):使用br标签及自身html属性
(对应清除float:both、float:left、float:right的影响)
<div class="clearFloatDiv1"> <div style="float: left;"></div> <div style="float: left;"></div> <br clear="all"/> //****闭合浮动 </div>
优点:比空标签方式语义稍强,代码量较少
缺点:同样有违结构与表现的分离,不推荐使用
方法四:父级元素定义 overflow: auto | hidden (为兼容ie6,还需触发hasLayout,如加: zoom: 1)
<div class="clearFloatDiv1" style="overflow:auto;"> //新建BFC <div style="float: left;"></div> <div style="float: left;"></div> </div>
overflow属性共有三个属性值:hidden,auto,visible。我们可以使用hiddent和auto值来清除浮动,但切记不能使用visible值。据说auto对seo比较友好, hidden对seo不是太友好。
优点:简单,代码少,浏览器支持好缺点
缺点:内部宽高超过父级div时,会出现滚动条。
方法五(差):父元素也设置浮动 float: left | right
<div class="clearFloatDiv1" **style="float: left;"**> //新建BFC <div style="float: left;"></div> <div style="float: left;"></div> </div>
优点:不存在结构和语义化问题,代码量极少
缺点:使得与父元素相邻的元素的布局会受到影响,不可能一直浮动到body,不推荐使用
方法六(差):父元素设置display:table
<div class="clearFloatDiv1" **style="display: table;"**> //新建BFC <div style="float: left;"></div> <div style="float: left;"></div> </div>
优点:结构语义化完全正确,代码量极少
缺点:盒模型属性已经改变,由此造成的一系列问题,得不偿失,不推荐使用