前端面试里,position 是一个永远绕不开的考点。很多同学平时写项目就是 relative + absolute
,顶多再来个 fixed
,但真到面试官问:
👉"absolute 和 fixed 的本质区别是什么?"
👉"为什么有时候 fixed 会跑到容器里面去?"
立马大脑宕机 ❌。
今天我们就来一次彻底梳理,从常见值到业务场景,再到浏览器底层,帮你把 position 五兄弟 一次性拿下。
Position
position
是 CSS 用来决定元素的定位方式的属性。它定义了一个元素在页面中的位置该如何计算
一、五个常见取值
static(默认值)
特点:元素按 文档流 正常排列,不受 top
、left
、right
、bottom
的影响。
应用场景:一般不用特意写,浏览器默认就是它。
relative(相对定位)
特点:相对定位,相对于自己原来的位置偏移,不脱离文档流。
absolute
(绝对定位)
特点:
- 相对于 最近的有定位(relative/absolute/fixed/sticky)的祖先元素 来定位。
- 如果往上找不到定位祖先,就相对
body
。 - 元素会 脱离文档流,不再占位置。
常见用法:让某个元素固定在容器的某个角落。
fixed
(固定定位)
-
特点:
- 相对于浏览器窗口定位,不随滚动条滚动。
- 同样脱离文档流。
-
常见用法:做导航栏、回到顶部按钮。
sticky
(粘性定位)
-
特点:
- 元素在一定范围内是相对定位的,超过某个阈值后,会像
fixed
一样粘在指定位置。 - 相对于最近的 滚动祖先元素 定位。
- 元素在一定范围内是相对定位的,超过某个阈值后,会像
-
常见用法:表头固定、吸顶导航。
二、业务场景应用
1. 消息提醒角标 ------ relative + absolute
ini
<div class="icon">
<span class="badge"></span>
</div>
css
.icon { position: relative; }
.badge {
position: absolute;
top: 0;
right: 0;
background: red;
border-radius: 50%;
width: 8px; height: 8px;
}
👉 父元素 relative
,子元素 absolute
定位到右上角。
2. 模态框居中 ------ absolute + transform
css
.modal {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
}
👉 先移动到 50%,再往回拉一半,完美居中。
3. 回到顶部按钮 ------ fixed
css
.back-top {
position: fixed;
bottom: 20px; right: 20px;
}
👉 滚动页面时,按钮永远钉在右下角。
4. 粘性导航 & 表头 ------ sticky
css
.nav { position: sticky; top: 0; }
th { position: sticky; top: 0; }
👉 吸顶效果不用 JS,sticky
就能搞定。
5. sticky
vs IntersectionObserver
两者都能实现"吸顶"效果,但原理和应用场景不同:
技术 | 原理 | 优点 | 缺点 | 适用场景 |
---|---|---|---|---|
sticky | CSS 控制,靠阈值自动切换 relative/fixed | 简单、纯 CSS,无需 JS | 兼容性有点坑,旧浏览器不行 | 导航吸顶、表头吸顶 |
IntersectionObserver | JS API 监听元素与视口交叉情况 | 精准控制,可触发任意逻辑 | 需要写 JS 代码 | 吸顶+动画、懒加载图片、无限滚动 |
三、底层原理
一、定位参照系(containing block)
元素一旦使用 position
,浏览器需要知道它到底是相对谁来定位的,也就是 containing block(包含块) 。
1. absolute
的参照系
- 规则:相对于最近的
position != static
的祖先元素定位; - 如果找不到 → 默认相对
body
(其实是初始包含块 initial containing block)。
👉 面试时要说:不是 body,而是 initial containing block(本质上是视口大小决定的矩形)。
2. fixed
的参照系
-
理论上:相对于 视口( viewport ) 定位;
-
但存在 "bug/例外" :
- 在 存在 transform、filter、perspective 等属性的祖先 内,
fixed
会失效,变成相对于这个祖先来定位(表现得像absolute
)。 - 因为这些属性会创建新的 containing block。
- 在 存在 transform、filter、perspective 等属性的祖先 内,
👉 所以面试官问到: "fixed
一定是相对视口吗?" 要答:不一定,如果祖先有 transform
,会改变 containing block。
3. sticky
的参照系
- 依赖最近的 可滚动容器 (带有
overflow: auto/scroll
)。 - 在超出阈值前表现为
relative
,超出后表现为fixed
。
👉 所以有时候你写 position: sticky
不生效,就是因为它的父容器不是滚动的,而 sticky 永远只盯着"谁能滚"。
二、独立图层渲染(stacking context & compositing layer)
除了参照系,position
还和 浏览器渲染机制 有关。浏览器会把页面拆成一个个 图层 layer 去渲染和合成。
1. absolute
是否创建新图层?
-
单纯的 absolute 不会 创建新的图层(compositing layer)。
-
但它会改变 层叠上下文 stacking context 的规则:
- 如果同时设置了
z-index
(且不是auto
),它会创建一个新的 stacking context。
- 如果同时设置了
👉 这意味着它的子元素会在独立的层叠环境里渲染,不再和外部兄弟元素互相干扰。
- 哪些情况会创建新图层?
浏览器优化时,会给某些元素单独开辟 GPU 合成层(compositing layer),常见触发条件:
position: fixed
(几乎总会单独分配图层,方便快速滚动合成)。will-change
(提示浏览器要优化)。transform / opacity / filter
。absolute/relative + z-index != auto
会创建新的 stacking context(不是合成层,但会影响绘制顺序)。
三、结合业务举例
-
absolute 消息角标
- 参照父容器(relative)。
- 没有设置
z-index
→ 不会新建图层; - 设置了
z-index: 1
→ 会创建 stacking context。
-
fixed 回到顶部按钮
- 默认参照视口。
- 浏览器通常会给它独立图层(合成层),因为要保证滚动流畅。
-
sticky 导航 吸顶
- 参照最近的滚动容器。
- 在切换 relative → fixed 的过程中,可能会触发 GPU 合成优化。
四、面试官常见提问套路
❓ absolute 和 fixed 的本质区别是什么?
👉 absolute 参照 containing block,fixed 理论上参照视口。
❓ 为什么 fixed 有时候"乱跑"?
👉 因为祖先加了 transform
/ filter
/ perspective
,改变了 containing block。
❓ 哪些情况会触发新图层?
👉 fixed、transform、opacity、filter、will-change。
五、总结
- static:默认,别管它。
- relative:定位参照,不脱流。
- absolute:脱流,参照最近有定位祖先。
- fixed:相对视口,但可能被 transform"绑架"。
- sticky:相对可滚动容器,relative ↔ fixed 的混合体。
从消息红点到吸顶导航,再到浏览器图层优化,掌握了 position,不仅能写出各种炫酷 UI,还能在面试时稳稳拿分。
📌 最后一句话总结:
会用 position,只能写业务;
懂 position,才能进大厂。