先记住这个答案
不会影响。position: relative 的元素先在正常文档流里排好位置,占掉该占的空间,然后 top、left 再把它相对原位置平移。平移只发生在绘制阶段,文档流里那块空间照样留着,所以兄弟元素的位置一点不变。结果就是元素挪走后原地留一块空白,挪过去的地方可能压住别的元素。
- 相对定位先占位再偏移,原位置保留
- 偏移后可能遮住别人,也可能留下空白
margin偏移会推动兄弟,top偏移不会- 最常见用途是给绝对定位子元素当参照物
看一个偏移前后的对比
三个横排的方块,把中间那个往右下挪一点,最直观。
<style>
.box { display: inline-block; width: 80px; height: 80px; }
.a { background: tomato; }
.b { background: gold; position: relative; top: 30px; left: 30px; }
.c { background: skyblue; }
</style>
<div class="box a">A</div>
<div class="box b">B</div>
<div class="box c">C</div>
<!-- B 向右下挪了 30px,压住了 C 的一部分 -->
<!-- B 原来的位置空出一块,C 没有往左补位 -->打开开发者工具看,B 的盒子轮廓已经画在右下方,但 C 的位置和不设偏移时完全一样。可以理解成 B 在排队时占了一个座位,然后人站到了旁边,座位还是它的,后面的人不会往前挪。
为什么偏移不影响别人
浏览器排版大致分两步:先算每个盒子在流里的位置和尺寸,再按位置把它们画出来。相对定位的偏移发生在第一步之后,算完所有兄弟的位置以后,才给这个元素加上一个位移量。兄弟元素在排版时参照的是 B 的原始位置,所以不会受影响。
这一点和 transform: translate() 很像,两者都是「占位不变、画的地方变了」。区别在于 transform 会创建层叠上下文和新的包含块,而且动画时通常只触发合成,性能更好;relative 加 top 动画会引起重新布局。做位移动画优先用 transform。
和 margin 对比就更清楚了。把 B 改成 margin-left: 30px,B 的盒子本身变宽了,C 会被往右推 30px。margin 改的是占位,top、left 改的只是画的位置。
真正常用的场景:给绝对定位当参照物
实际项目里,position: relative 很少用来挪位置,更多是不写任何偏移,只为了让它成为包含块。包含块就是绝对定位元素计算 top、left 时参照的那个矩形。
- 角标定位在卡片右上角
.card { position: relative; }配上.badge { position: absolute; top: 8px; right: 8px; },角标就贴在卡片右上角。如果卡片不设relative,角标会继续往上找最近的定位祖先,找不到就相对初始包含块,常常跑到页面右上角去。因为relative不写偏移时对自身布局没有任何影响,所以它是做这件事最省心的选择。
容易答错的地方
- 以为
relative会让元素脱离文档流 - 脱离文档流的是
absolute和fixed,它们不占原来的空间,后面的元素会补上来。relative始终在流里,这是它和absolute最核心的区别。 - 以为偏移后原位置会被兄弟填上
- 偏移后原地留下的是空白,不会有元素补位。想要既挪动又不留空,应该改
margin或者用 flex、grid 的对齐,而不是用top、left。 - 以为同时写
top和bottom能拉伸元素 - 绝对定位同时写
top和bottom能撑开高度,相对定位不行。两者都写时bottom直接被忽略;水平方向在从左到右的文字方向下left优先。
面试官还会怎么问?
相对定位的元素偏移后会盖住别人吗,谁在上面?
会盖住。定位元素的绘制顺序排在普通流里的块级和行内内容之后,所以即使 z-index 是 auto,偏移后的 relative 元素通常也会画在没定位的兄弟上面。如果对方也是定位元素,再按 z-index 和 DOM 顺序比较。
top: 50% 在相对定位里是相对谁算的?
百分比参照包含块的高度,也就是父元素的内容区高度。如果父元素高度是 auto,百分比的 top 在相对定位下会被当成 auto,也就是不偏移。水平方向的 left 百分比参照包含块宽度,一般都能生效。
做元素位移动画,用 relative 加 top 还是 transform?
用 transform。top 变化会触发布局计算,每帧都可能重排;transform 一般只在合成阶段处理,不影响布局,动画更流畅。两者在「不影响兄弟位置」这点上是一样的。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。