CSS 元素的浮动和定位
# CSS Float(浮动)
# 1. 什么是 CSS Float(浮动)
- 基本概念
CSS 的
float
属性可以使元素向左或向右移动,周围的元素(处于正常文档流中的元素)也会重新排列以围绕被浮动的元素。最常见的用途是使文本环绕图像,但在早期网页布局中,float 也常被用来实现多列布局。 - 默认行为
在没有指定
float
属性时,元素通常会按照文档流从上到下依次排列。当对某个元素设置float: left
或float: right
之后,该元素会“脱离”正常文档流,向指定方向尽可能“贴边”。
正常文档流元素是贴紧页面的,而脱离文档流元素就会浮动起来,不会独占一行,如下图所示:
注意: 脱离文档流的元素所占空间是默认被内容撑开的(宽度和高度由内容决定),即使该元素是块级元素也不会独占一行;
常见用途
- 图文混排:图片与文字环绕排版。
- 简易多列布局:在 Flex、Grid 出现之前,float 常被用来创建多列布局
# 2. 元素浮动后的特点
- 元素的浮动只作用于水平方向,意味着它会向左或向右贴边,而在垂直方向上不改变原有顺序。
- 被设置为浮动的元素会尽量靠近包含块(父容器)的左或右边缘;如果有相邻的浮动元素,也会彼此紧挨排布,直到遇到边界才会换行。
- 浮动元素后的普通文档流元素会围绕该浮动元素进行环绕排布;不过,在浮动元素之前的元素不受影响,依然保持原有的布局顺序。
- 不会独占一行,可以与其他元素共用一行。
- 不会margin合并,也不会margin塌陷,能够完美的设置四个方向的margin和padding。
- 不会像行内块一样被当做文本处理(没有行内块的空白问题)。
在浮动元素对齐时,它们会朝着 父容器的左侧或右侧边缘的最顶部对齐,这是浮动的一个重要特点。更具体地说:
- 左浮动时:元素会尽可能向左移动,直到它的左边缘碰到父容器的左侧边界或另一个浮动元素的右边缘。
- 右浮动时:元素会尽可能向右移动,直到它的右边缘碰到父容器的右侧边界或另一个浮动元素的左边缘。
- 顶部对齐规则:无论是左浮动还是右浮动,浮动元素会尽量“向上贴紧”,即与它的容器顶部或相邻浮动元素的顶部对齐。即使后续有多个浮动元素,它们会在有足够空间的情况下保持对齐。
右浮动示例:当一张图片设置为 float: right
时,其后的文字将自动围绕在图片左侧,如以下示例所示:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
img {
float: right; /* 使图片浮动到右侧 */
}
</style>
</head>
<body>
<p>在下面的段落中,我们添加了一个 <b>float:right</b> 的图片。导致图片将会浮动在段落的右边。</p>
<p>
<img src="logocss.gif" width="95" height="84" />
这是一些文本。这是一些文本。这是一些文本。
这是一些文本。这是一些文本。这是一些文本。
这是一些文本。这是一些文本。这是一些文本。
这是一些文本。这是一些文本。这是一些文本。
这是一些文本。这是一些文本。这是一些文本。
这是一些文本。这是一些文本。这是一些文本。
这是一些文本。这是一些文本。这是一些文本。
这是一些文本。这是一些文本。这是一些文本。
这是一些文本。这是一些文本。这是一些文本。
</p>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 3. 彼此相邻的浮动元素
如果在同一个容器中把多个元素都设置为 float
,并且它们的宽度之和未超过容器宽度,那么这些浮动的元素会彼此相邻排列。
在这里,我们对图片廊使用 float 属性:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
.thumbnail {
float: left; /* 使缩略图浮动到左侧 */
width: 110px;
height: 90px;
margin: 5px; /* 设置缩略图之间的间距 */
}
</style>
</head>
<body>
<h3>图片库</h3>
<p>试着调整窗口,看看当图片没有足够的空间会发生什么。</p>
<img class="thumbnail" src="/images/klematis_small.jpg" width="107" height="90">
<img class="thumbnail" src="/images/klematis2_small.jpg" width="107" height="80">
<img class="thumbnail" src="/images/klematis3_small.jpg" width="116" height="90">
<img class="thumbnail" src="/images/klematis4_small.jpg" width="120" height="90">
<img class="thumbnail" src="/images/klematis_small.jpg" width="107" height="90">
<img class="thumbnail" src="/images/klematis2_small.jpg" width="107" height="80">
<img class="thumbnail" src="/images/klematis3_small.jpg" width="116" height="90">
<img class="thumbnail" src="/images/klematis4_small.jpg" width="120" height="90">
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
当浏览器窗口够宽时,这些图片会一行接一行地紧密排列;当空间不足时,图片会自动换行浮动到下一行。效果如下:
# 4. 清除浮动 - 使用 clear
当元素浮动后,后续文档流中的元素会围绕它排布。某些情况下,我们希望后面或特定的块级元素能够在浮动元素的下面正常显示,而不是环绕。这时就可以使用 clear
属性。
clear
指定了在元素的哪一侧(左侧、右侧、或两侧)不允许有浮动元素。- 常见取值:
clear: left;
表示元素的左侧不允许有浮动元素。clear: right;
表示元素的右侧不允许有浮动元素。clear: both;
表示元素的两侧都不允许有浮动元素。
下面我们在图片廊和下一段内容之间使用了 clear: both;
,从而使下方文字避免被上方图片环绕:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
.thumbnail {
float: left; /* 使缩略图浮动到左侧 */
width: 110px;
height: 90px;
margin: 5px; /* 设置缩略图之间的间距 */
}
.text_line {
clear: both; /* 清除左右两侧的浮动 */
margin-bottom: 2px; /* 设置段落底部的间距 */
}
</style>
</head>
<body>
<h3>图片库</h3>
<p>试着调整窗口,看看当图片没有足够的空间会发生什么。</p>
<img class="thumbnail" src="/images/klematis_small.jpg" width="107" height="90">
<img class="thumbnail" src="/images/klematis2_small.jpg" width="107" height="80">
<img class="thumbnail" src="/images/klematis3_small.jpg" width="116" height="90">
<img class="thumbnail" src="/images/klematis4_small.jpg" width="120" height="90">
<h3 class="text_line">第二行</h3>
<img class="thumbnail" src="/images/klematis_small.jpg" width="107" height="90">
<img class="thumbnail" src="/images/klematis2_small.jpg" width="107" height="80">
<img class="thumbnail" src="/images/klematis3_small.jpg" width="116" height="90">
<img class="thumbnail" src="/images/klematis4_small.jpg" width="120" height="90">
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 5. CSS 中所有的浮动属性
在 CSS 中,与 float
和清除浮动相关的属性主要有以下几种:
float
- 取值:
none | left | right | inherit
- 功能:指定元素的浮动方向或不浮动。
- 取值:
clear
- 取值:
none | left | right | both | inherit
- 功能:指定元素的哪一侧不允许出现浮动元素。
- 取值:
display
(间接相关)- 虽然
float
不直接影响display
,但块级元素和行内元素的特性对浮动布局都有影响。例如float
通常与块级元素结合更好。
- 虽然
position
(间接相关)float
与position
有不同的定位机制,不应混淆。一个元素同时使用float
和position
时往往会产生复杂的渲染效果,除非有特殊需求,不建议混用。
# 6. 常见错误和改进
- 未对容器清除浮动
如果一个父容器内的子元素都设置了
float
,而父容器本身没有清除浮动,则可能导致父容器高度塌陷,影响后续布局。 - 错误地使用
clear
如果不恰当地对某些元素设置clear
,可能会破坏布局,造成元素过早或过晚地换行。 - 滥用浮动实现复杂布局
在现代布局中,使用
Flexbox
或CSS Grid
更直观且功能更强大。浮动更多是用于文字环绕等特定场景。
可以使用 clearfix(清除浮动)技术
为了解决父元素因为内部子元素浮动而导致高度无法被正常撑开的现象,我们常在父容器中使用一个 “clearfix” 技术,让父容器自动包裹、清除内部浮动。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
.container::after {
content: "";
display: table;
clear: both; /* 清除容器内部的浮动 */
}
.thumbnail {
float: left; /* 使缩略图浮动到左侧 */
width: 110px;
height: 90px;
margin: 5px; /* 设置缩略图之间的间距 */
}
</style>
</head>
<body>
<div class="container">
<h3>图片库</h3>
<p>试着调整窗口,看看当图片没有足够的空间会发生什么。</p>
<img class="thumbnail" src="/images/klematis_small.jpg" width="107" height="90">
<img class="thumbnail" src="/images/klematis2_small.jpg" width="107" height="80">
<img class="thumbnail" src="/images/klematis3_small.jpg" width="116" height="90">
<img class="thumbnail" src="/images/klematis4_small.jpg" width="120" height="90">
<h3 class="text_line">第二行</h3>
<img class="thumbnail" src="/images/klematis_small.jpg" width="107" height="90">
<img class="thumbnail" src="/images/klematis2_small.jpg" width="107" height="80">
<img class="thumbnail" src="/images/klematis3_small.jpg" width="116" height="90">
<img class="thumbnail" src="/images/klematis4_small.jpg" width="120" height="90">
</div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
以上 .container::after
的设置会在 .container
的最后生成一个伪元素(在视觉上不可见),通过 clear: both;
将浮动清除,从而让 .container
能够正确根据其内容自动计算并呈现高度。
# CSS 元素的定位
position
属性用于控制元素在页面中的定位方式。它有以下五个可选值:
static
(默认)relative
absolute
fixed
sticky
当元素被设置了特定的定位(非 static
)后,才可使用 top
、bottom
、left
、right
等属性来控制元素的位置。元素的最终位置还会受到所选定位类型的影响,例如相对于其最靠近的已定位父元素、浏览器窗口、滚动位置等。
# 1. 静态定位 - static
position: static
是所有 HTML 元素的默认定位方式,元素按照正常文档流排列,不会因为 static
而移动,也不会响应 top
、bottom
、left
、right
等偏移属性。
如果没有为元素显式设置任何
position
属性,浏览器就会将该元素默认为position: static
。也就是说,「不写position
」与「写position: static
」在视觉和布局上呈现相同效果。
- 不会脱离普通文档流,依照页面从上到下的正常排版顺序。
- 不支持使用
top
、bottom
、left
、right
对其定位进行改变。 - 常用于“重置”某些定位属性,或保留元素默认的流式布局。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
div.static {
position: static; /* 静态定位 */
border: 3px solid #73AD21; /* 绿色边框 */
}
</style>
</head>
<body>
<h2>position: static;</h2>
<p>使用 position: static; 定位的元素,无特殊定位,遵循正常的文档流对象:</p>
<div class="static">
该元素使用了 position: static;
</div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 2. 固定定位 - fixed
position: fixed
让元素相对于浏览器窗口固定不动,无论页面如何滚动,都保持在固定位置。
- 元素从正常文档流中完全脱离,不占据原来的空间。
- 不会随页面滚动而移动,常用于悬浮导航栏、回到顶部按钮等。
- 在老版本 IE(IE7、IE8)下使用需要确保有标准的
<!DOCTYPE>
声明,否则可能不生效。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
p.pos_fixed {
position: fixed; /* 固定定位 */
top: 30px; /* 距离顶部30像素 */
right: 5px; /* 距离右侧5像素 */
}
</style>
</head>
<body>
<p class="pos_fixed">这是一段固定定位的文本</p>
<p><b>注意:</b> IE7 和 IE8 支持 fixed 定位需要一个 !DOCTYPE 声明。</p>
<p>滚动页面以查看效果。</p>
<p>Some text</p><p>Some text</p><p>Some text</p><p>Some text</p><p>Some text</p><p>Some text</p><p>Some text</p><p>Some text</p><p>Some text</p><p>Some text</p><p>Some text</p><p>Some text</p><p>Some text</p><p>Some text</p><p>Some text</p><p>Some text</p>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
注意: Fixed 定位在 IE7 和 IE8 下需要描述 !DOCTYPE 才能支持。
- Fixed 定位使元素的位置与文档流无关,因此不占据空间。
- Fixed 定位的元素会与其他元素重叠。
# 3. 相对定位 - relative
使用 position: relative
会使元素在正常文档流中保持位置,然后通过 top
、left
、right
、bottom
等属性做相对它本身原始位置的偏移。
- 保留元素在文档流中的占位,不会影响其他元素的布局。
- 移动后,周围元素依旧按照它原本所占空间排布。
- 常用作建立包含块,给内部绝对定位的元素(
position: absolute
)提供参考系。
示例 1:相对于自身原位左右移动
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
h2.pos_left {
position: relative; /* 相对定位 */
left: -20px; /* 向左移动20像素 */
}
h2.pos_right {
position: relative; /* 相对定位 */
left: 20px; /* 向右移动20像素 */
}
</style>
</head>
<body>
<h2>这是位于正常位置的标题</h2>
<h2 class="pos_left">这个标题相对于其正常位置向左移动</h2>
<h2 class="pos_right">这个标题相对于其正常位置向右移动</h2>
<p>相对定位会按照元素的原始位置对该元素进行移动。</p>
<p>样式 "left:-20px" 从元素的原始左侧位置减去 20 像素。</p>
<p>样式 "left:20px" 向元素的原始左侧位置增加 20 像素。</p>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
h2.pos_top {
position: relative; /* 相对定位 */
top: -50px; /* 向上移动50像素 */
}
</style>
</head>
<body>
<h2>这是一个没有定位的标题</h2>
<h2 class="pos_top">这个标题是根据其正常位置向上移动</h2>
<p><b>注意:</b> 即使相对定位元素的内容是移动, 预留空间的元素仍保存在正常流动。</p>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
相对定位元素经常被用来作为绝对定位元素的容器块。
# 4. 绝对定位 - absolute
使用 position: absolute
的元素将脱离文档流,相对于“最近的已定位祖先元素”进行定位。如果没有找到已定位的祖先元素,那么它将相对于 <html>
(即浏览器视口)来定位。
- 不再保留原本在文档流中的空间,可能与其他元素产生重叠。
- 如果父元素没有设置任何定位(
static
除外),元素就以整个文档或浏览器窗口为参考。 - 常用于搭配
relative
定位的父元素,使布局更可控。
设置绝对定位的步骤:
选择或设置定位参考
- 如果元素需要在整个页面中绝对定位,可直接使用
position: absolute;
。它会相对于最靠近的已定位祖先元素(若无则相对<html>
)进行定位。 - 如果只想在一个特定容器内做绝对定位,则先给该容器加
position: relative;
(或其他非static
定位),作为定位参考点。
- 如果元素需要在整个页面中绝对定位,可直接使用
为目标元素设定绝对定位
.child { position: absolute; }
1
2
3- 这样,元素脱离正常文档流,不再占据原本位置。
指定偏移量
通过
top
,right
,bottom
,left
属性控制元素与参考点的距离,例如:.child { top: 20px; /* 距离父容器顶部 20px */ left: 50px; /* 距离父容器左侧 50px */ }
1
2
3
4数值越大,元素越远离对应边缘。
处理重叠层级(可选)
如果可能与其他元素重叠,可以使用
z-index
调整堆叠顺序:.child { z-index: 10; /* 值越大,越在上层 */ }
1
2
3
完成以上操作后,元素即可在指定容器或页面中任意位置进行绝对定位,并与周围正常文档流的元素产生分离。
示例:在容器右上角显示徽章
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>绝对定位案例</title>
<style>
/* 父容器设置相对定位,使子元素(徽章)以此为参考点 */
.container {
position: relative;
width: 300px;
height: 200px;
margin: 50px auto; /* 让容器水平居中,只是为了演示美观 */
border: 2px solid #ccc;
background-color: #f9f9f9;
}
/* 普通文档流内容 */
.container p {
padding: 10px;
margin: 0;
}
/* 绝对定位徽章 */
.badge {
position: absolute; /* 脱离文档流,定位参考 .container */
top: 10px; /* 距离父元素顶部 10px */
right: 10px; /* 距离父元素右侧 10px */
background-color: red;
color: #fff;
padding: 5px 10px;
border-radius: 3px;
font-weight: bold;
}
</style>
</head>
<body>
<h2>绝对定位示例:在容器右上角显示徽章</h2>
<div class="container">
<p>这里是一个商品信息卡片或任意容器内容。</p>
<p>通过给父容器 <code>position: relative</code>,再将徽章进行绝对定位至容器右上角。</p>
<div class="badge">HOT</div>
</div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 5. 粘性定位 - sticky
sticky
基于用户的滚动位置来定位。在 position:relative
与 position:fixed
定位之间切换。
粘性定位的核心思路?
position: sticky
的元素在尚未达到设置的阈值(如top: 0
)之前,表现得跟position: relative
一样——也就是说,它依旧处在文档流中,正常往下排列。- 一旦页面滚动到让该元素到达「离顶部
top: x
」的位置时,它会切换成跟position: fixed
类似的效果,固定在视口的那个位置,不再跟随滚动而移动。 - 用一句话概括: 当你滚动页面时,元素会先随着内容往上滚动,直到元素自身顶部与视口
top
属性指定的位置“贴合”后,元素就“粘”在那儿了,直到它的父容器被进一步滚动出去(或滚动完成)。
设置粘性定位的步骤:
- 保证父元素可产生滚动
- 父容器需要有足够高度并且允许滚动(
overflow: auto;
或overflow: scroll;
),这样才能在滚动过程中触发粘性定位效果。
- 父容器需要有足够高度并且允许滚动(
- 设置粘性定位与阈值
- 为目标元素设置
position: sticky;
(在 Safari 中还需-webkit-sticky;
)。 - 指定至少一个阈值,如
top: 0;
、left: 0;
等。当元素滚动到这个阈值时,便会吸附或“黏”在对应位置。
- 为目标元素设置
- 触发前后表现形式
- 在尚未到达阈值时,元素与普通
relative
定位效果相同,随文档流正常滚动。 - 一旦滚动至阈值位置,元素会变为类似
fixed
的行为,固定在指定的阈值处不再跟随内容继续滚动。
- 在尚未到达阈值时,元素与普通
- 浏览器兼容性
- IE/Edge 15 及更早版本不支持
position: sticky
;Safari 需要-webkit-
前缀才能生效。 - 对需要兼容较早版本浏览器的项目,可能需使用替代方案(如 JS 实现吸顶效果)。
- IE/Edge 15 及更早版本不支持
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
div.sticky {
position: -webkit-sticky; /* Safari 使用 -webkit- 前缀 */
position: sticky; /* 粘性定位 */
top: 0; /* 滚动到顶部时固定 */
padding: 5px;
background-color: #cae8ca;
border: 2px solid #4CAF50;
}
</style>
</head>
<body>
<p>尝试滚动页面。</p>
<p>注意: IE/Edge 15 及更早 IE 版本不支持 sticky 属性。</p>
<div class="sticky">我是粘性定位!</div>
<div style="padding-bottom:2000px">
<p>滚动我</p>
<p>来回滚动我</p>
<p>滚动我</p
>
<p>来回滚动我</p>
<p>滚动我</p>
<p>来回滚动我</p>
</div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
为什么有时 `position: sticky` 不生效?
- 父元素高度或滚动设置问题:
如果父容器本身没有发生滚动,而你又把
sticky
放在一个不具备滚动条的容器里,效果就很难察觉。一般需要给父容器overflow: auto;
或overflow: scroll;
并有足够高度,才能看到粘性定位发挥作用。 - 没有指定阈值:
如果不写
top
,left
,bottom
,right
中任意一个,sticky
会退化为relative
效果。最常见的是top: 0;
。 - 浏览器兼容性:
- IE、Edge 15 及更早版本不支持。
- Safari 需要加
-webkit-sticky;
前缀。
- 被父元素的
overflow: hidden
或其他属性影响: 如果父容器设置了overflow
属性导致元素被剪裁,也会干扰粘性定位的表现。
# 6. 元素重叠 - z-index
当元素采取非静态定位(如 absolute
, fixed
, relative
, sticky
)时,它们可能彼此重叠。z-index
决定了在发生重叠时,哪个元素位于前面。
- z-index 的取值
- 可以是正数、负数或 0。
- 数值越大,元素越靠上方堆叠。
- 没有设置
z-index
的定位元素,默认堆叠顺序受其在文档中出现的顺序影响:后出现的会覆盖先出现的。
- 注意
z-index
只对那些具有定位的元素(非static
)起作用。- 若元素未脱离文档流(如
static
),即使给它设置z-index
也不会产生预期的层叠效果。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
img {
position: absolute; /* 绝对定位 */
left: 0px;
top: 0px;
z-index: -1; /* 设置 z-index 为 -1,使其显示在文字后面 */
}
</style>
</head>
<body>
<h1>This is a heading</h1>
<img src="w3css.gif" width="100" height="140" />
<p>因为图像元素设置了 z-index 属性值为 -1, 所以它会显示在文字之后。</p>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
注意: 如果两个定位元素重叠,没有指定 z-index
,最后定位在 HTML 代码中的元素将被显示在最前面。