深入理解css浮动
一、浮动介绍
历史:浮动最早的效果是为了实现文字环绕图片
文字和图片放在一起时,文字与图片的下方对齐,想要实现文字环绕图片(文字与图片的上方对齐),使用float,例如:
给照片加了float:left后的效果:
Note:
1.浮动,根据字面意思,就是浮起来了,想象一下,浮动的元素漂浮在了其他元素的上方,可添加margin ,占到外面容器的宽的时候,会换到下一行(站队的边界是父级的边界)
2.浮动元素脱离正常流,意思是布局时后面元素当它不存在(只有块级元素看不到它们,文本类属性的元素还是当它存在的,环绕其身边),但仍然在dom树上。
3.如果是在js中通过element.style设置元素浮动,需要用cssFloat,因为float是js中的一个关键字。【IE8及以下浏览器用styleFloat】
如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#father {
border: 1px solid red;
}
#test {
background-color: green;
/* float: left; */
}
.brother{
width: 100px;
height: 100px;
background: blue;
}
</style>
</head>
<body>
<div id="father">
<span id="test">span内容</span>
</div>
<div class="brother"></div>
<script type="text/javascript">
var oSpan=document.getElementById("test");
oSpan.style["cssFloat" in oSpan.style? "cssFloat" : "styleFloat"]="left";
</script>
</body>
</html>
没加浮动的效果:
加了浮动的效果:
二、包裹性
包裹性指的是元素尺寸刚好容纳内容。
具有包裹性的其他属性:
- display:inline-block/table-cell/…
- position:absolute/fixed/sticky
- overflow:hidden/scroll
通过例子看看浮动的包裹性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
border: 1px solid green;
padding: 30px;
background-color: green;
/*将背景裁剪到内容框,方便看浮动元素效果*/
background-clip: content-box;
}
.fl {
float: left;
}
</style>
</head>
<body>
<div class="container fl">
内容
</div>
</body>
</html>
包裹性原理
浮动之所以会产生包裹性这样的效果是因为float属性会改变元素display属性最终的计算值。
设置float前的display属性 >> 设置浮动后的display属性计算值
- inline >> block
- inline-block >> block
- inline-table >> table
- table-row >> block
- table-row-group >> block
- table-column >> block
- table-column-group >> block
- table-caption >> block
- table-header-group >> block
- table-footer-group >> blcok
- flex >> flex
- inline-flex >> inline-flex【inline-flex在chrome下测试,float后display:flex】
- other >> unchanged
可以利用浮动的包裹性来达到父容器自适应内部元素宽度
三、破坏性
通过第一个例子可以看出元素浮动后,导致父元素不能包住浮动元素,高度塌陷了。
其他破坏性的属性:
- display:none
- position:absolute/fixed/sticky
原理:因为浮动元素脱离了文档流,父元素仍然处在文档流中,所以父元素不能被浮动元素撑大。
四、清除浮动
clear属性
clear属性规定元素的哪一侧不允许有其他浮动元素。
取值:
- left:元素左侧不允许有浮动元素
- right:元素右侧不允许有浮动元素
- both:元素左右两侧均不允许有浮动元素
- none:默认值,允许浮动元素出现在两侧
清除浮动的三个方法:
1.兄弟元素设置clear:both
2.用父级的伪元素消除浮动流
3.将父级元素(是块级元素)变成BFC元素
方法一:兄弟元素设置clear:both
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#father {
border: 1px solid red;
}
#test {
background-color: green;
float: left;
}
.brother{
width: 100px;
height: 100px;
background: blue;
}
</style>
</head>
<body>
<div id="father">
<span id="test">span内容</span>
</div>
<div class="brother" style="clear: both;"></div>
</body>
</html>
效果前:
效果后:
可以看到,在兄弟元素上加了clear:both后,兄弟元素让开了浮动元素的位置,但父元素还是没有包住浮动元素,这种方法不好用,pass掉。
方法二:用父级的伪元素消除浮动流
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#father {
border: 1px solid red;
}
#test {
background-color: green;
float: left;
}
.brother{
width: 100px;
height: 100px;
background: blue;
}
#father::after{
content: '';
display: block;
clear: both;
}
</style>
</head>
<body>
<div id="father">
<span id="test">span内容</span>
</div>
<div class="brother"></div>
</body>
</html>
效果后:
nice!,实现了父元素包住浮动元素了,兄弟元素也让了位置,好用!!!,再看最后一种方法。
方法三:将父级元素(是块级元素)变成BFC元素
补充BFC知识
BFC:块级格式化上下文【在css3中叫Flow Root】是一个独立布局环境,相邻盒子margin垂直方向会重叠。
什么样的元素会为其内容生成一个BFC呢?
- 浮动元素,即float:left|right
- 绝对定位元素,即position:absolute|fixed
- 块容器,(比如inline-blocks,table-cells和table-captions),这些块容器有个特征就是它们不是块级盒子。即display:table-cell|table-caption|inline-block
- 设置了除visible外的overflow值的块盒子,即overflow:hidden|scroll|auto
BFC特性:
- 创建了BFC的元素中,子浮动元素也会参与高度计算
- 与浮动元素相邻的、创建了BFC的元素,都不能与浮动元素相互覆盖
- 创建了BFC的元素不会与它们的子元素margin重叠
这里选用overflow:hidden清除浮动,其余的可以自己动手试试看。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#father {
border: 1px solid red;
overflow: hidden;
}
#test {
background-color: green;
float: left;
}
.brother{
width: 100px;
height: 100px;
background: blue;
}
</style>
</head>
<body>
<div id="father">
<span id="test">span内容</span>
</div>
<div class="brother"></div>
</body>
</html>
PS:
clear:both和BFC的区别:前者可以发生margin重叠,BFC不会有margin重叠
BFC的缺点:
1、不能应用于所有场合,因为不可能所有元素都绝对定位或者不可能所有元素都浮动。
2、现代浏览器不认识zoom:1。
五、总结
每种清除浮动的方法都有弊端,权衡后推荐用法:
.clearfix::after{
content:"";
display:block;
height:0;
overflow:hidden;
clear:both;
}
/*IE6和IE7*/
.clearfix{
*zoom:1;
}
或者:
.clearfix:after{
content:"";
display:table;
clear:both;
}
/*IE6和IE7*/
.clearfix{
*zoom:1;
}
注:.clearfix类只应该用在包含浮动元素的父元素上
六:浮动布局
1.普通固定布局
通常用的浮动布局一般是:固定尺寸+浮动。
例如:两行布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
width: 700px;
}
.left {
width: 150px;
float: left;
}
.right {
width: 450px;
float: right;
}
</style>
</head>
<body>
<div class="left">
<img
src="https://bkimg.cdn.bcebos.com/pic/730e0cf3d7ca7bcb3409f115bf096b63f624a89d?x-bce-process=image/resize,m_lfit,w_220,limit_1/format,f_auto" />
</div>
<div class="right">
文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容
</div>
</body>
</html>
问题:
容错性差:容器尺寸变了,就得改代码。
复用性不好:尺寸固定,模块在另外尺寸容器中不能重用。
2.推荐布局
(1)左侧尺寸固定右侧自适应的流体布局
在上面代码基础上修改样式为
<style type="text/css">
.left{
width: 150px;
float: left;
}
/*流体布局*/
.right {
margin-left: 150px;
}
</style>
重点是使用margin-left,且不要定宽。这样好处是容器尺寸变化右侧可自适应。
(2)右侧尺寸固定左侧自适应的流体布局
改变DOM位置的流体布局写法
写代码时顺序为先右后左,这样就可以设置右栏右浮动,左栏设置margin-right
<style type="text/css">
.right{
float: right;
width: 150px;
}
.left{
margin-right: 150px;
}
</style>
</head>
<body>
<div class="right">
<img src="img/wb.jpg">
</div>
<div class="left">
文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容
</div>
</body>
不改变DOM位置的流体布局写法【左右栏都左浮动】
写代码时顺序不变,左右栏都浮动,通过margin调整位置。
<style type="text/css">
.wrap {
width: 100%;
float: left;
}
.left {
margin-right: 150px;
}
.right {
width: 150px;
float: left;
margin-left: -150px;
}
</style>
<body>
<div class="wrap">
<div class="left">
文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容
</div>
</div>
<div class="right">
<img src="img/wb.jpg">
</div>
</body>
效果同上。
(3)两栏都自适应的布局
原理是左栏浮动,右栏生成BFC,根据BFC特性与浮动元素相邻的、创建了BFC的元素,都不能与浮动元素相互覆盖。
<style type="text/css">
.left {
float: left;
}
.right{
display: table-cell;
}
</style>
<body>
<div class="left">
<img src="img/wb.jpg"/>
</div>
<div class="right">
文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容文本内容
</div>
</body>
七、float布局和inline-block布局对比
浮动和inline-block都能让元素排成一排,那么两者之间怎么区分呢?下面对比一下。
- 文档流:浮动元素脱离正常流,让文字环绕。inline-block仍然在正常流中。
- 水平位置:不能通过给父元素设置text-align:center让浮动元素无法水平居中【因为脱离文档流】,而inline-block可以。
- 垂直对齐:浮动元素紧贴顶部,inline-block默认基线对齐,可通过vertical-align调整。
- 空白:浮动忽略空白元素彼此紧靠,inline-block保留空白。
举例:浮动布局可以去掉元素之间的空格,而inline-block会保留空格
<style>
button {
margin: 0;
float: left;
}
p {
clear: both;
}
</style>
</head>
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
</body>
button默认display:inline-block;可见他们之间有空格的距离。加了float:left后各个button元素之间空格消失。
总结:处理文字环绕自然是用浮动,处理图片列表垂直对齐或者横向导航可以选择inline-block。