五种定位 + z-index 层级 + 实战场景 + 新手常见坑,新手向超详细完整版
前言
学 CSS 布局的时候,以为布局很简单,结果一做项目就发现:弹窗怎么居中?导航栏怎么吸顶?侧边栏怎么悬浮?图标怎么精准放到文字旁边?
全都需要 position 定位。
可五种定位值各有各的规矩,relative 和 absolute 的区别、fixed 和 sticky 什么时候用、z-index 为什么有时候不生效……踩了一堆坑才慢慢理清楚。
这篇文章把定位布局的所有知识点、代码示例、实战场景、新手常踩的坑,一次性讲透。
一、定位布局是干什么的?
一句话:自由控制元素在页面上的精准位置。
标准文档流里,元素从上到下、从左到右老老实实排队。但有些效果文档流做不到:
- 悬浮客服按钮
- 固定顶部导航栏
- 弹窗遮罩层
- 侧边目录
- 吸顶表头
这些都需要用 position 让元素"跳出队列",放到你想要的位置。
⚠️ 重要:不是所有定位都脱离文档流!
| 定位值 | 是否脱离文档流 |
|---|---|
static | ❌ 不脱离,正常排队 |
relative | ❌ 不脱离,原位置占位 |
absolute | ✅ 完全脱离,不占位 |
fixed | ✅ 完全脱离,不占位 |
sticky | ❌ 不脱离(滚动时表现为 fixed,但仍占位) |
基本语法:
.box {
position: 定位值; /* static / relative / absolute / fixed / sticky */
top: 10px; /* 向下偏移 10px */
left: 20px; /* 向右偏移 20px */
/* right / bottom 同理 */
}
二、五种定位值详解
1. static 静态定位(默认值)
所有元素默认就是 static,不写 position 和写了 position: static 效果完全一样。
特点:
- 不脱离文档流,老老实实排队
top、left、right、bottom全部无效z-index也无效
用途:唯一用途就是取消其他定位,恢复默认。
/* 默认状态,什么都不做 */
.box {
position: static;
top: 100px; /* ❌ 无效,不会偏移 */
}
/* 实际用途:取消定位 */
.box {
position: absolute;
/* 一堆定位操作... */
}
/* 某个场景下想恢复默认 */
.box {
position: static; /* ✅ 取消定位,回到文档流 */
}
2. relative 相对定位
核心特点:不脱离文档流,相对于自身原始位置偏移。
什么叫"偏自身"?你坐在教室座位上,身体往前挪一点,但座位依旧是你的,别人坐不了。
请注意:相对定位的占坑大小不变,偏移出去的区域不属于它的占位,也不挤占别人空间
四大必记特点:
| 特点 | 说明 |
|---|---|
| 不脱离文档流 | 原位置继续占位,旁边元素不会挤过来 |
| 参照物是自身 | 以没定位之前的位置为基准偏移,和父盒子无关 |
| 不影响其他元素 | 自己挪位置,别人不动 |
| z-index 生效 | 可以设置层级盖住其他元素 |
偏移方向易错点:
| 属性 | 正数方向 | 负数方向 |
|---|---|---|
top | ⬇️ 向下 | ⬆️ 向上 |
left | ➡️ 向右 | ⬅️ 向左 |
bottom | ⬆️ 向上 | ⬇️ 向下 |
right | ⬅️ 向左 | ➡️ 向右 |
/* 基础用法:微调位置 */
.box {
position: relative;
left: 30px; /* 从自己原来位置,向右移 30px */
top: 20px; /* 从自己原来位置,向下移 20px */
}
/* 最常用场景:给绝对定位当父级参照物(子绝父相) */
.parent {
position: relative; /* 只当参照物,不偏移 */
width: 500px;
height: 500px;
}
.child {
position: absolute; /* 子元素相对父元素定位 */
top: 10px;
right: 10px;
}
/* 实际场景:图标和文字对齐微调 */
.icon-text {
position: relative;
top: 2px; /* 图标偏上,往下挪 2px 和文字对齐 */
}
新手最容易踩的 5 个坑:
- 用 relative 做页面整体布局 → ❌ 大忌!占位还在,容易出现大片空白
- 以为 relative 能居中 → ❌ 居中优先用 flex / grid
- 多个 relative 互相堆叠 → ❌ 极易重叠错乱
- left 设过大 → ❌ 超出可视区,出现横向滚动条
- 用 relative 做悬浮栏 → ❌ 滚动时跟着页面走,做不了悬浮
relative 和不写 position 相比,获得了移动的能力,常用于div 盒子中的各种标签,未读标签的小红点等等...
3. absolute 绝对定位(重点)
核心特点:完全脱离文档流,不占位置,找最近的已定位祖先做参照物。
三大必记特点:
| 特点 | 说明 |
|---|---|
| 完全脱离文档流 | 不占位置,其他元素当它不存在 |
| 参照物是最近的已定位祖先 | 父元素有定位(非 static)→ 相对父元素;父无定位 → 相对浏览器视口 |
| 最常用搭配:子绝父相 | 父 relative + 子 absolute |
/* 经典场景:父相子绝,子元素放到父元素右上角 */
.father {
position: relative;
width: 300px;
height: 300px;
background: #f0f0f0;
}
.son {
position: absolute;
top: 0;
right: 0;
background: red;
color: white;
padding: 4px 8px;
}
/* 经典场景:水平垂直居中 */
.father {
position: relative;
width: 500px;
height: 500px;
}
.son {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%); /* 往回挪自身宽高的一半 */
}
/* 实际场景:商品卡片上的角标 */
.card {
position: relative;
width: 200px;
height: 250px;
}
.badge {
position: absolute;
top: -10px;
left: -10px;
background: red;
color: white;
border-radius: 50%;
width: 40px;
height: 40px;
}
⚠️ 注意:绝对定位元素不占位,会覆盖其他元素。如果不想覆盖,需要手动设置 z-index 或给父容器留出空间。
4. fixed 固定定位
核心特点:脱离文档流,参照物永远是浏览器视口,页面滚动也纹丝不动。
三大必记特点:
| 特点 | 说明 |
|---|---|
| 脱离文档流 | 不占位置 |
| 参照物是浏览器窗口 | 不是父元素,不是页面,是屏幕 |
| 滚动不动 | 页面怎么滚,它都在原地 |
/* 经典场景:固定顶部导航栏 */
.nav {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 60px;
background: white;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
z-index: 999;
}
/* 经典场景:右下角回到顶部按钮 */
.back-top {
position: fixed;
right: 20px;
bottom: 30px;
width: 44px;
height: 44px;
background: #409eff;
color: white;
border-radius: 50%;
}
/* 经典场景:右侧悬浮客服 */
.customer-service {
position: fixed;
right: 0;
top: 50%;
transform: translateY(-50%);
}
⚠️ 注意:使用 fixed 时,页面其他内容会被它覆盖,记得给 body 或主内容区加 padding-top(固定导航栏)或 margin-right(侧边栏)留出空间。
5. sticky 粘性定位
核心特点:混合了 relative 和 fixed 的行为,滚动到阈值时"吸住"。
工作原理:
- 滚动前:表现为
relative,正常占位 - 滚动到阈值(
top指定的值):切换为fixed,吸住不动 - 滚出父容器范围:恢复
relative,跟着页面走
/* 经典场景:导航吸顶 */
.sticky-nav {
position: sticky;
top: 0; /* 距离顶部 0px 时吸顶 */
background: white;
z-index: 100;
}
/* 实际场景:表格表头固定 */
.table-container {
height: 400px;
overflow-y: auto;
}
.table-header {
position: sticky;
top: 0;
background: #fafafa;
}
/* 实际场景:侧边目录高亮跟随 */
.sidebar {
position: sticky;
top: 80px; /* 距离顶部 80px 时吸住(留出导航栏高度) */
}
⚠️ 注意:
sticky必须指定top/left等阈值,否则不会生效- 只在父容器范围内生效,滚出父级就失效
- 父容器不能有
overflow: hidden,否则 sticky 会失效
三、relative vs fixed 做侧边栏,到底有什么区别?
这个问题我一开始也搞混了,两种定位都能做出侧边栏的样子,但行为完全不同。
核心区别
| 对比项 | relative 侧边栏 | fixed 侧边栏 |
|---|---|---|
| 参照物 | 自身原始位置 | 浏览器视口 |
| 是否占位 | ✅ 占位,原位置留空 | ❌ 不占位,脱离文档流 |
| 滚动行为 | 跟着页面一起滚走 | 永远钉在屏幕上 |
| 适用场景 | 跟着内容走的侧边栏 | 常驻悬浮侧边栏 |
/* relative 侧边栏:随页面滚动 */
.side-relative {
position: relative;
left: 0;
top: 100px;
width: 200px;
}
/* 页面往下滚 → 侧边栏跟着消失 */
/* fixed 侧边栏:永久悬浮 */
.side-fixed {
position: fixed;
right: 20px;
top: 150px;
width: 200px;
}
/* 页面怎么滚 → 侧边栏始终在屏幕右侧 */
一句话总结:同样能做出侧边栏外观,relative 依附文档流跟随页面流动,fixed 依附浏览器窗口永久悬浮。开发中悬浮控件一律用 fixed,局部微调位置用 relative。
如果你要做一个"文章目录",希望滚动时目录始终可见,我会用 fixed,它不占位,脱离文档流,能实现常驻。
四、定位层级 z-index
z-index 控制定位元素的堆叠顺序,数值越大越靠上。
核心规则:
| 规则 | 说明 |
|---|---|
| 只对定位元素生效 | position: static 的元素设置 z-index 无效 |
| 数值越大层级越高 | 支持正负整数,默认 z-index: auto |
| 同级定位后写在上 | 没有 z-index 时,后面的元素盖住前面的 |
| 只影响同级元素 | 不会跨父元素比较 |
/* 基础用法 */
.box1 {
position: absolute;
z-index: 1; /* 在下层 */
}
.box2 {
position: absolute;
z-index: 10; /* 在上层,盖住 box1 */
}
/* 实际场景:弹窗遮罩层 */
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 1000; /* 遮罩层 */
}
.modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 1001; /* 弹窗在遮罩层上面 */
}
/* ⚠️ z-index 不生效的常见原因 */
.parent {
position: relative;
z-index: 1; /* 父元素创建了层叠上下文 */
}
/* 子元素 z-index 再高,也不会超过另一个 z-index 更高的父元素的子元素 */
.child {
position: absolute;
z-index: 9999; /* 仍然受限于父元素的层叠上下文 */
}
⚠️ z-index 不生效的常见原因:
- 元素没有设置
position(或设为static) - 父元素创建了新的层叠上下文(设置了
transform、opacity、filter等) - 同一父元素内的子元素,
z-index只在同级之间比较
五、五种定位速记口诀
| 定位 | 占位 | 参照物 | 滚动行为 | 一句话 |
|---|---|---|---|---|
static | ✅ | 无 | 正常 | 默认无效果,取消定位用 |
relative | ✅ | 自身 | 跟着走 | 留空位,偏自身,做父级 |
absolute | ❌ | 已定位父级 | 跟着走 | 不占位,找父级,自由放 |
fixed | ❌ | 浏览器视口 | 不动 | 不占位,盯窗口,做悬浮 |
sticky | ✅→❌ | 视口(阈值内) | 吸住 | 滚动切换,区间吸顶 |
六、实战场景速查表
| 场景 | 推荐定位 | 代码要点 |
|---|---|---|
| 元素微调位置 | relative | top / left 小幅偏移 |
| 盒子内部放小图标 | 父 relative + 子 absolute | 子绝父相 |
| 弹窗 + 遮罩层 | fixed + z-index | 遮罩 1000,弹窗 1001 |
| 全局固定导航栏 | fixed + top: 0 | 记得给 body 加 padding-top |
| 滚动吸顶导航 | sticky + top: 0 | 父容器不能有 overflow: hidden |
| 水平垂直居中 | absolute + transform | top: 50%; left: 50%; translate(-50%, -50%) |
| 商品卡片角标 | 父 relative + 子 absolute | top: -10px; left: -10px |
| 右下角回到顶部 | fixed + right/bottom | right: 20px; bottom: 30px |
总结
CSS 定位是页面布局的灵魂属性。浮动适合横向排列,Flex 适合一维弹性布局,Grid 适合二维排版,而定位布局主打精准控位,是实现网页特殊视觉效果、交互悬浮效果必不可少的核心技术。
不用死记硬背五种定位的所有细节,记住核心区别就够了:
relative:占位置,偏自身,专做父级与微调absolute:不占位,找父级,自由摆放fixed:不占位,盯窗口,做悬浮sticky:滚动切换,区间吸顶static:默认无效果
日常开发中,90% 的场景都是"子绝父相"和 fixed 悬浮,把这两个用熟,定位布局就算入门了。
CSS里面的学问很深,有时定位出bug,很有可能是你某个知识点没有掌握,但是一步一个脚印,其实CSS也不难
路漫漫其修远兮,吾将上下而求索
💡 建议补充:可以配一张思维导图,把五种定位的关系和区别可视化