**position: relative 相对元素自己在文档流中的原位置偏移,不脱离文档流,原位置继续占位;position: absolute 脱离文档流、原位置不占位,相对最近的非 static 定位祖先的 padding box 定位。**记住这一句,绝大多数布局问题就能判断清楚。
position: relative 和 absolute 的核心区别是什么?
结论:两者的根本差异在于“是否脱离文档流”和“以谁为定位基准”。
relative 元素的偏移量(top/right/bottom/left)是相对它本来应该在的位置计算的,偏移后其他元素的位置完全不变,等于它“人挪了、位子还留着”;absolute 元素则直接退出文档流,后面的元素会顶上来占据它原来的空间。
另一个差异是基准不同:relative 的偏移基准是自己的原始位置,absolute 的偏移基准是包含块(containing block,即最近一个 position 不为 static 的祖先元素的 padding box)。所以同一个 top: 20px,在 relative 上是“往下挪 20px”,在 absolute 上是“贴到祖先内容区内边距上沿往下 20px”。
position: relative 怎么用?定位基准是哪里?
结论:relative 最常见的用途不是做偏移,而是给 absolute 子元素做定位参照,以及做微调。
.box {
position: relative;
top: 2px; /* 相对原位置下移 2px,原空间保留 */
left: -1px;
}
关键点有三条:
- 不写 top/left 时,relative 元素在视觉上与 static 无任何差别,但已经具备“可被 absolute 作为参照”的能力。
- 偏移量支持负值,百分比按包含块的宽度(左右)和高度(上下)计算,不是按自身尺寸。
- 只要设置了
position: relative 且 z-index 不为 auto,就会创建新的层叠上下文(stacking context),影响子元素和伪元素的层级关系。
position: absolute 怎么用?它相对谁定位?
结论:absolute 沿祖先链向上找第一个 position 为 relative / absolute / fixed / sticky 的元素作为包含块,找不到就相对初始包含块(initial containing block,尺寸等于视口、位于文档原点)定位。
.parent { position: relative; width: 400px; height: 300px; }
.badge { position: absolute; top: 0; right: 0; }
必须清楚的三个细节:
- absolute 元素设了
width: auto 时宽度会收缩到内容宽度(shrink-to-fit),不像块级元素撑满父级,所以要显式给宽或用 left: 0; right: 0; 拉伸。
- 包含块是祖先的 padding box,即 padding 边缘以内、border 以外,所以父元素有 border 时子元素的
top: 0 贴在 padding 上沿而不是 border 外沿。
- 祖先如果有
transform、filter、perspective、will-change: transform 或 contain: paint,会强制成为新的包含块,即使它的 position 是 static。这一点常被忽视:弹窗明明 position: fixed 却跟着某个卡片跑,原因就在此。
为什么“子绝父相”是最常用组合?
结论:父元素 position: relative 定基准、子元素 position: absolute 定位置,是叠加角标、下拉菜单、遮罩层、关闭按钮的标准写法。
父级用 relative 只为了划出参照范围,不写偏移量就不会影响自身布局;子级用 absolute 精确贴边或居中。居中写法:
.center {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
left: 50% 让元素左边缘落在包含块中线,translate(-50%, -50%) 按自身宽高的一半回拉,得到真正的几何居中。
absolute 元素为什么撑不开父元素高度?
结论:因为 absolute 元素脱离文档流,不参与父元素的高度计算,父元素高度只由普通流内容决定。
三种处理方式按场景选:
- 父元素直接给固定高度(如
height: 300px),适合尺寸确定的卡片、轮播。
- 父元素用
aspect-ratio: 16 / 9 让高度跟随宽度,避免塌陷。
- 父元素保留一个普通流占位元素(或
min-height)撑住高度,absolute 元素仅做装饰层。
同理,absolute 元素用 height: 100% 时,百分比相对包含块高度计算,若包含块高度是 auto,计算结果会回退为内容高度,表现就是“高度没生效”。
三个高频踩坑点
结论:overflow、z-index、滚动跟随是 relative/absolute 组合最容易出问题的地方。
- 祖先带
overflow: hidden 会裁掉 absolute 子元素超出部分;需要溢出显示时,要么把裁剪层放到包含块之外,要么改用 fixed 定位层。
- 同级 absolute 元素的层叠顺序取决于 z-index 与 DOM 顺序,z-index 为 auto 时不创建层叠上下文,容易被更上层祖先整体压住,调不上去。
- absolute 元素随文档滚动,fixed 不随文档滚动;但只要祖先有 transform,fixed 也会退化成类似 absolute 的行为。
把这两条记牢:relative 是“挪位置、留空位、可当基准”,absolute 是“退出文档流、找最近的定位祖先、收缩到内容宽度”。写布局前先问一句“它的包含块是哪个元素”,绝大多数错位问题都能自己定位出来。