10.4 浮动定位方案
浮动float严格讲属于定位方案,同时它广泛的运用于列式布局,也称作float布局。
列式布局目前主要有两种方案:float列式布局、flex列式布局。flex列式布局提供各种强大功能,约10个CSS属性。浮动布局功能简单,只有1个属性。float的优点:简单、不支持弹性。很多网站的PC端前台仍使用float布局,一方面考虑兼容问题,另一方面因为页面需要精准尺寸不允许弹性。
术语说明。float元素指float: left或right的元素。
10.4.1 float特点经典场景
float特点经典场景包括两个场景。
场景1:跨多个行盒line box。float元素跨一个IFC内多个line box,常见于图文环绕。
示例代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小步教程</title>
<style>
.div1{
background-color: #ed7d31;
}
.div1::first-line{
background-color: #0aaa76;
padding-left: 20px;
}
</style>
</head>
<body>
<div class="div1">
<img src="image/logo.jpg" style="float: left;margin-right: 10px;">
小步教程 xiaobuteach.com 很长的一段文字描述,
很长的一段文字描述很长的一段文字描述很长的一段文字描述,
很长的一段文字描述很长的一段文字描述很长的一段文字描述,
很长的一段文字描述很长的一段文字描述很长的一段文字描述。
</div>
</body>
</html>
float表示左浮。伪元素::first-line选择第1个行盒line box。
运行效果
场景2:跨多个div。float元素在垂直方向跨多个div。
代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小步教程</title>
<style>
.parent{
background-color: #0aaa76;
}
.float{
float:left ;
height: 100px;
background-color: #4aa6fc;
}
.div2{
background-color: #ed7d31;
}
</style>
</head>
<body>
<div class="parent">
<div class="float">浮动内容</div>
<div class="div1">
<span>div1 小步教程 xiaobuteach.com</span>
<span>小步教程 xiaobuteach.com</span>
<span>小步教程 xiaobuteach.com</span>
</div>
</div>
<div class="div2">div2</div>
</body>
</html>
父元素包含float元素,float元素高度是100px。父元素包含非浮动内容,又包含浮动内容;下方还有一个块。
运行效果
说明父元素parent高度height: auto计算具体值时,不会参考float元素的高度,会参考其它正常流定位元素的高度,所以导致下一个div也显示在float元素的右边。
10.4.2 float盒子特点
特点1:float盒子具有占位。float元素同一行的行盒line box的宽度相应变小,下方行盒识别到float元素高度而排列在下方。所以float元素与正常流定位元素不会重叠。
特点2:float盒子高度不参与父盒高度计算。上述两个示例证明父元素具备识别内部float元素的宽度与高度的能力,特意设计成不采纳它的高度。这个设计保证float元素能跨多个行盒与跨多个div。
特点3:所属BFC的创建元素能识别浮动元素高度,查看各元素的offsetHeight验证。查看parent、body、html三个盒子的offset高度。
根元素html的offsetHeight包含了float元素的高度。
特点4:float盒子半脱离流。从两个角度理解float盒子是否脱离流:(1)从完全自动计算坐标的角度,属于脱离流定位;(2)从占位角度,存在占位,影响后续元素位置。综合所述,float通常称为脱离流或半脱离流。
10.4.3 父盒识别float盒子高度
父盒识别float盒子高度主要包括两种方法。
(1)新建BFC识别高度。可通过display: flow-root或overflow: hidden等方式实现。
<div class="parent" style="display: flow-root;">
(2)clear方法清除浮动。父元素内部结束添加clear:both的子元素,或通过伪类实现。
.parent::after{
content:'';
display:block;
clear:both;
}
运行效果说明父元素识别其高度,计算样式面板查看parent高度进一步验证。
10.4.4 float经典错误场景
float特点经典场景2页面效果
这是实际项目经常出现的经典错误场景,换成如下页面内容可能更熟悉。
“菜单项2”这个float元素的高度超出父元素的高度,占据下方div第1个行盒的相应位置,导致内容右移。
问题代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小步教程</title>
<style>
.parent{
background-color: #0aaa76;
height: 20px;
}
.float{
float:left ;
height: 20px;
background-color: #4aa6fc;
}
.div2{
background-color: #ed7d31;
}
.parent::after{
content:'';
display:block;
clear:both;
}
</style>
</head>
<body>
<div class="parent">
<div class="float">菜单项1</div>
<div class="float" style="height: 23px;">菜单项2</div>
<div class="float">菜单项3</div>
</div>
<div class="div2">主体内容 小步教程 xiaobuteach.com</div>
</body>
</html>
parent高度20px,“菜单项2”高度23px超出,即使21px也出现同样问题。
多种解决方法:(1)调整float元素高度小于等于父div高度,(2)溢出内容进行隐藏。如果是不小心设置过高则需用第1种方法。
10.4.5 float列式布局与浮动塌陷
前面研究了float元素的本质,接下来讲解float用于列式布局。
float布局实现一行多列包括两个步骤:各列设置浮动;clear属性清除浮动。
(1)单行场景
例1:一行三列。先不清浮除动。
<body>
<div>
<div style="float: left;width: 100px;">
<div>第1行第1列</div>
<div>小步教程</div>
</div>
<div style="float: left;width: 150px;">
<div>第1行第2列</div>
<div>xiaobuteach.com</div>
</div>
<div style="float: left;width: 150px;">
<div>第1行第3列</div>
<div>每列可嵌套复杂布局</div>
</div>
</div>
</body>
运行效果正常
(2)下一行上移现象
例2:共3行,第1行分3列。
<body>
<div>
<div style="float: left;width: 100px;">第1行第1列</div>
<div style="float: left;width: 100px;">第1行第2列</div>
<div style="float: left;width: 100px;">第1行第3列</div>
</div>
<div>第2行</div>
<div>第3行 小步教程 xiaobuteach.com</div>
</body>
运行结果不正常。
第2行没有换行,第3行正常换行,这就是浮动塌陷。
(3)浮动塌陷
开发者工具查看第1行的div的实际高度等于0。
浮动塌陷:父div如果没有设置高度则根据内部内容自动计算;当子div设置float属性为left或right,父div计算高度时不会参考它的高度;当一个父div的所有子元素全是float,父元素的高度则为0。当父div后续还有div则会导到上移现象。
10.4.6 解决浮动塌陷的四种方法
方法1:设置clear:both来清除浮动。在最后一个float列之后添加clear:both的div。
<div>
<div style="float: left;width: 100px;">第1行第1列</div>
<div style="float: left;width: 100px;">第1行第2列</div>
<div style="float: left;width: 100px;">第1行第3列</div>
<div style="clear: both;"></div>
</div>
清除浮动的div的位置与其它列元素并列。运行效果如下。
开发者工具查看父div高度正常。
方法2:伪元素清除浮动。伪元素::after实现添加上一步的专用div,本质同方法1。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>CSS 伪类清除浮动 | 小步教程</title>
<style>
.clearfix::after {
content: '';
display: block;
clear: both;
}
</style>
</head>
<body>
<div class="clearfix">
<div style="float: left;width: 100px;">1行1列</div>
<div style="float: left;width: 100px;">1行2列</div>
<div style="float: left;width: 100px;">1行3列</div>
</div>
<div>第2行</div>
<div>第3行 小步教程 xiaobuteach.com</div>
</body>
</html>
实际项目会把clearfix类放在公用CSS文件。
方法3:BFC方案。设置overflow:flow-root创建新的BFC,方法本质是:所属BFC的创建元素能识别浮动元素高度。
<body>
<div style="overflow: flow-root;">
<div style="float: left;width: 100px;">1行1列</div>
<div style="float: left;width: 100px;">1行2列</div>
<div style="float: left;width: 100px;">1行3列</div>
</div>
<div>第2行</div>
<div>第3行 小步教程 xiaobuteach.com</div>
</body>
运行效果正常。
方法4:设置塌陷元素的高度。当浮动元素高度较小,父div手动设置较大高度,也会正常显示。如果父元素没有手动设置高度,而内部还存在其它的普通子元素(非float),且普通子元素高度大于float元素高度,也能正常显示。
10.4.7 float自动换行
父div包含多列float元素,如果一行排列不下则自动换行。
示例代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小步教程</title>
</head>
<body>
<div style="width: 450px;border: 1px solid #666;display: flow-root;">
<div style="float: left;width: 100px;background-color: #0aaa76;">
<div>第1行第1列</div>
<div>小步教程</div>
</div>
<div style="float: left;width: 150px;background-color: #4aa6fc;">
<div>第1行第2列</div>
<div>xiaobuteach.com</div>
</div>
<div style="float: left;width: 150px;background-color: #ed7d31;">
<div>第1行第3列</div>
<div>每列可嵌套复杂布局</div>
</div>
</div>
</body>
</html>
父div内容宽度450px,3列总宽度400px,则在一行显示。
调整第3列宽度为200px,则刚好完全占满一行。
调整第3列宽度为201px,一行放不下则整列自动换行。
float元素自动换行的三种场景。
场景1:正常应用场景。典型场景是商品列表分多行显示,无需直接指定行数,会根据内部float元素个数及相关宽度而自动换行产生相应行数。
场景2:错误场景。部分场景不需要换行,因为尺寸设计错误导致float列宽之和超出父div宽度,此时自动换行成为错误,需相应调整float元素列宽与父div宽度。
场景3:溢出内容进行显示。部分特殊场景允许float列宽之和超出父div宽度,但不允许换行,超出内容也称溢出内容,需要对溢出内容进行显示。float本身不支持不自动换行,可改成flex布局,或者间接实现。间接实现思路:float父div设计足够容纳float各列的宽度,float爷div设计目标宽度,父div默认会在爷div溢出显示,因为overflow默认值visible表示针对溢出进行显示。
示例代码如下
<body>
<div style="width: 400px;border: 1px solid #666;">
<div style="border: 1px solid #c00;display: flow-root;width: 500px;">
<div style="float: left;width: 100px;background-color: #0aaa76;">
<div>第1行第1列</div>
<div>小步教程</div>
</div>
<div style="float: left;width: 150px;background-color: #4aa6fc;">
<div>第1行第2列</div>
<div>xiaobuteach.com</div>
</div>
<div style="float: left;width: 200px;background-color: #ed7d31;">
<div>第1行第3列</div>
<div>每列可嵌套复杂布局</div>
</div>
</div>
</div>
</body>
运行效果
10.4.8 float右对齐
<div>元素a</div>
<div>元素b</div>
假设上述两个元素设置成右对齐float: right,浏览器渲染过程按代码顺序渲染,首先将元素a放在最右,然后将元素b放在该行剩块空间的最右,所以最终效果先b再a。如果想按a、b顺序显示在右,可以使用如下结构,在外层div设置一个float: right即可。
<div>
<div>元素a</div>
<div>元素b</div>
</div>