Skip to content

定位 ​

普通文档流会按元素顺序安排页面。定位用于角标、局部覆盖、弹层关闭按钮和固定操作等特殊位置,不承担后台页面的主布局。

认识 position 与偏移属性 ​

css
.element {
    position: static;
}
值主要特点
static默认,按普通文档流排列,偏移属性不生效
relative保留原位置,可相对自身偏移,也可建立定位参考
absolute脱离普通文档流,相对定位包含块放置
fixed脱离普通文档流,通常相对视口固定

本节不把定位当作“想放哪里就放哪里”的坐标工具。先保持正常结构,只在局部确有需要时使用。

偏移属性

定位元素可以使用:

css
.element {
    top: 12px;
    right: 16px;
    bottom: 20px;
    left: 24px;
}

通常只需要确定水平和垂直方向各一项,例如 top + right。同时写 left、right 或 top、bottom 时还会影响自动尺寸,初学阶段避免无意混用。

建立局部定位关系 ​

使用相对定位建立参考 ​

css
.status-badge {
    position: relative;
    top: -2px;
}

relative 元素仍保留原来的布局空间,视觉上可以相对自身位置偏移。原位置不会由其他元素补上。

更常见的用途是为内部绝对定位元素建立参考:

css
.student-card {
    position: relative;
}

如果不需要偏移,就不必写 top、left。

案例:

html
<!doctype html>
<html lang="zh-CN">
	<head>
		<meta charset="utf-8" />
		<title></title>
		<style>
			#father {
				margin-top: 30px;
				margin-left: 30px;
				border: 1px solid silver;
				background-color: lightskyblue;
			}

			#father div {
				width: 100px;
				height: 60px;
				margin: 10px;
				background-color: hotpink;
				color: white;
				border: 1px solid white;
			}

			#son2 {
				/*这里设置 son2 的定位方式*/
			}
		</style>
	</head>
	<body>
		<div id="father">
			<div id="son1">第 1 个无定位的 `div` 元素</div>
			<div id="son2">相对定位的 `div` 元素</div>
			<div id="son3">第 2 个无定位的 `div` 元素</div>
		</div>
	</body>
</html>

未设置偏移前,三个盒子仍按普通文档流排列:

初始状态:三个盒子依次排列
第 1 个普通盒子
待设置相对定位
第 2 个普通盒子

使用绝对定位局部覆盖 ​

html

<article class="student-card">
    <span class="student-badge">新学员</span>
    <h2>张三</h2>
    <p>FastAPI Web 1 班</p>
</article>
css
.student-card {
    position: relative;
    padding: 24px;
}

.student-badge {
    position: absolute;
    top: 12px;
    right: 12px;
}
新学员
张三
FastAPI Web 1 班

绝对定位元素脱离普通文档流,不再为自己保留空间。这里的参考通常是最近的、position 不为 static 的祖先。

口诀“父相子绝”只能作为常见组合,不是语法要求:

  • 父元素也可以是其他非 static 定位。
  • 子元素只有确实需要局部覆盖时才绝对定位。
  • 如果没有合适的定位祖先,它可能相对更外层的初始包含块定位,造成位置失控。

举例:

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8"/>
    <title></title>
    <style>
        #father {
            padding: 15px;background-color: #0C6A9D;border: 1px solid silver;
        }
        #father div {padding: 10px;}
        #son1 {background-color: #FCD568;}
        #son2 {background-color: hotpink;/*在这里添加 son2 的定位方式*/}
        #son3 {background-color: lightskyblue;}
    </style>
</head>
<body>
<div id="father">
    <div id="son1">box1</div>
    <div id="son2">box2</div>
    <div id="son3">box3</div>
</div>
</body>
</html>

未添加定位时,三个盒子在普通文档流中依次排列:

未定位:box2 仍占据中间的位置
box1
box2
box3

我们为第 2 个 div 元素加入绝对定位,CSS 代码如下:

css
#son2 {
	position: absolute;
	top: 20px;
	right: 40px;
}

此时 box2 脱离普通文档流,box3 上移并紧接 box1。下方用一个局部容器模拟浏览器视口,避免预览元素定位到整页课件的右上角:

绝对定位:box2 不再占据中间的位置
box1
box2
box3

分析:

在这份独立 HTML 中,#father 没有设置定位属性,#son2 也没有就近的非 static 定位祖先,因此 top 和 right 参照初始包含块,通常可以按浏览器视口理解。预览中的局部容器只用于模拟这个参照范围。绝对定位可使用 top、right、bottom、left 指定位置;这个例子通过 top 和 right 确定了位置。

为覆盖内容预留空间 ​

绝对定位的角标不占空间,可能遮住标题:

css
.student-card {
    position: relative;
    padding: 24px 96px 24px 24px;
}

右侧增加内边距,为角标预留区域。定位成功不代表内容不会重叠,还要测试。

将元素固定到视口 ​

css
.back-to-top {
    position: fixed;
    right: 24px;
    bottom: 24px;
    width: 44px;
    height: 44px;
}

固定定位元素通常相对浏览器视口放置,页面滚动时仍停在原处。适合返回顶部、固定帮助入口或遮罩层。

固定顶栏也会脱离普通文档流:

css
.topbar {
    position: fixed;
    top: 0;
    right: 0;
    left: 0;
    height: 64px;
}

.page {
    padding-top: 64px;
}

必须为主体预留空间,否则顶栏会覆盖正文。综合后台案例更倾向使用正常 Flex 结构,只有明确要求始终固定时才这样处理。

案例:

html

<style>
    #first {
        width: 120px;
        height: 1800px;
        border: 1px solid gray;
        line-height: 600px;
        background-color: #b7f1ff;
    }

    #second {
        position: fixed; /*设置元素为固定定位*/
        top: 30px; /*距离浏览器顶部 30px*/
        left: 160px; /*距离浏览器左部 160px*/
        width: 60px;
        height: 60px;
        border: 1px solid silver;
        background-color: hotpink;
    }
</style>

<div id="first">无定位的 `div` 元素</div>
<div id="second">固定定位的 `div` 元素</div>

下方用局部滚动区域模拟浏览器视口。滚动蓝色长盒子时,粉色盒子会留在示意视口的同一位置:

滚动示意视口,观察粉色盒子的位置
普通盒子
固定
盒子
预览用局部容器模拟视口;独立运行上方代码时,fixed 元素参照浏览器视口。

固定定位最常用于实现“回顶部特效”,这个效果非常经典。为了更好的用户体验,绝大多数网站都用上。此外,回顶部特效还可以做得非常酷炫。

回到顶部按钮:青绿色圆角方块中的白色向上箭头

处理覆盖与层级 ​

使用 z-index 控制层级 ​

css
.topbar {
    position: fixed;
    z-index: 100;
}

.dialog-mask {
    position: fixed;
    z-index: 1000;
}

z-index 控制层叠顺序,但结果还会受到层叠上下文影响。基础项目遵循两个原则:

  1. 只在发生覆盖关系的组件上设置。
  2. 使用少量约定层级,不把数值不断增加到极大。

如果 z-index 没有效果,先检查元素的定位、祖先是否创建了独立层叠上下文,以及比较的元素是否处在同一上下文,而不是直接改成 999999。

搭建遮罩与对话框 ​

下面只观察定位关系,不实现打开和关闭交互:

html

<div class="dialog-mask">
    <section class="dialog" role="dialog" aria-labelledby="dialog-title">
        <button class="dialog-close" type="button" aria-label="关闭">×</button>
        <h2 id="dialog-title">删除学员</h2>
        <p>确认删除张三吗?</p>
    </section>
</div>
css
.dialog-mask {
    position: fixed;
    z-index: 1000;
    inset: 0;
    background-color: rgb(15 23 42 / 55%);
}

.dialog {
    position: absolute;
    top: 50%;
    left: 50%;
    width: min(420px, calc(100% - 32px));
    padding: 24px;
    transform: translate(-50%, -50%);
    border-radius: 12px;
    background-color: #ffffff;
}

.dialog-close {
    position: absolute;
    top: 12px;
    right: 12px;
}
学员列表
张三 · 在读
删除学员
确认删除张三吗?

inset: 0 等价于四个方向都为 0。transform 在这里只用于把对话框中心对准视口中心。

完成带角标的学员卡片 ​

html

<article class="student-card">
    <span class="student-badge">待审核</span>
    <h2>王小明</h2>
    <p>报名课程:FastAPI Web 全栈</p>
    <p>报名时间:2026-07-16</p>
</article>
css
.student-card {
    position: relative;
    max-width: 420px;
    padding: 24px 112px 24px 24px;
    border: 1px solid #d9e1ec;
    border-radius: 12px;
    background-color: #ffffff;
}

.student-badge {
    position: absolute;
    top: 16px;
    right: 16px;
    padding: 4px 10px;
    border-radius: 999px;
    background-color: #fff7e6;
    color: #ad4e00;
    font-size: 13px;
}
待审核
王小明
报名课程:FastAPI Web 全栈
报名时间:2026-07-16

这是定位擅长的局部任务:角标覆盖在卡片右上角。多张卡片怎样排列,交给下一节 Flex。

小结 ​

  1. 相对定位保留原空间,并常用于建立绝对定位参考。
  2. 绝对与固定定位脱离普通文档流,要防止内容重叠。
  3. “父相子绝”是常见组合,不是所有布局的通用方案。
  4. z-index 只解决有明确覆盖关系的层级问题。
  5. 定位负责局部覆盖,页面主布局交给 Flex。
定位练习源码
html
<!doctype html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>相对定位练习</title>
    <style>
        #father {
            margin-top: 30px;
            margin-left: 30px;
            border: 1px solid silver;
            background-color: lightskyblue;
        }

        #father div {
            width: 100px;
            height: 60px;
            margin: 10px;
            background-color: hotpink;
            color: white;
            border: 1px solid white;
        }

        #son2 {
            /* 在这里设置 son2 的定位方式 */
        }
    </style>
</head>
<body>
<div id="father">
    <div id="son1">第 1 个无定位的 `div` 元素</div>
    <div id="son2">相对定位的 `div` 元素</div>
    <div id="son3">第 2 个无定位的 `div` 元素</div>
</div>
</body>
</html>
html
<!doctype html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>定位遮罩与对话框</title>
    <style>
        .dialog-mask {
            position: fixed;
            z-index: 1000;
            inset: 0;
            background-color: rgb(15 23 42 / 55%);
        }

        .dialog {
            position: absolute;
            top: 50%;
            left: 50%;
            width: min(420px, calc(100% - 32px));
            padding: 24px;
            transform: translate(-50%, -50%);
            border-radius: 12px;
            background-color: #ffffff;
        }

        .dialog-close {
            position: absolute;
            top: 12px;
            right: 12px;
        }
    </style>
</head>
<body>
<div class="dialog-mask">
    <section class="dialog" role="dialog" aria-labelledby="dialog-title">
        <button class="dialog-close" type="button" aria-label="关闭">×</button>
        <h2 id="dialog-title">删除学员</h2>
        <p>确认删除张三吗?</p>
    </section>
</div>
</body>
</html>
html
<!doctype html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>带角标的学员卡片</title>
    <style>
        .student-card {
            position: relative;
            max-width: 420px;
            padding: 24px 112px 24px 24px;
            border: 1px solid #d9e1ec;
            border-radius: 12px;
            background-color: #ffffff;
        }

        .student-badge {
            position: absolute;
            top: 16px;
            right: 16px;
            padding: 4px 10px;
            border-radius: 999px;
            background-color: #fff7e6;
            color: #ad4e00;
            font-size: 13px;
        }
    </style>
</head>
<body>
<article class="student-card">
    <span class="student-badge">待审核</span>
    <h2>王小明</h2>
    <p>报名课程:FastAPI Web 全栈</p>
    <p>报名时间:2026-07-16</p>
</article>
</body>
</html>