Skip to content

✨ 定位 👌

视觉格式化模型(布局规则)大体上将页面中盒子的排列分为三种方式:

  1. 常规流
  2. 浮动:float
  3. 定位:position

定位用于手动控制元素在包含块中的精准位置,常用于悬浮按钮、弹层、提示气泡、固定导航等场景。


1. 基本概念

  • position 决定元素是否参与常规文档流以及如何计算偏移。
  • 只要 position 不是 static,该元素被视为“定位元素”。除 relative 外,其余定位都会脱离文档流。
  • 脱离文档流的元素:
    • 常规流元素的排列会忽略它。
    • 常规流容器的自动高度不会包含它。

TIP

定位是精确摆放的利器,但并非通用布局方案。优先考虑 Flex/Grid,定位用于局部微调或悬浮/覆盖类效果。


2. position 属性与取值

  • static(默认):静态定位,不脱离文档流,偏移属性无效。
  • relative:相对定位,不脱离文档流,允许使用 top/right/bottom/left 在“原位置”基础上偏移。
  • absolute:绝对定位,脱离文档流,偏移相对于“包含块”计算(见下文)。宽高为 auto 时适应内容。
  • fixed:固定定位,通常相对于视口(浏览器可视区域)固定位置,常用于固定头部/悬浮按钮。
  • sticky:粘性定位,介于 relativefixed 之间;在滚动到阈值前表现为相对定位,达到阈值后“吸附”在指定位置。

TIP

sticky 常用于吸顶导航:在接近顶部时吸附停靠,离开区域后恢复原位。


3. 包含块(containing block)与偏移

偏移属性 top/right/bottom/left 表示元素与“包含块”的距离。

  • 绝对定位(absolute):
    • 查找祖先中“第一个定位元素”(positionstatic)。该祖先的填充盒(padding box)作为包含块。
    • 若未找到,则包含块为初始包含块(通常是页面根元素区域)。
  • 固定定位(fixed):
    • 一般以视口作为包含块。
    • 某些情况下(如祖先有 transform/filter 等创建新的包含块)会改为该祖先。
  • 相对/粘性定位:
    • 相对定位以自身原始位置为参考进行偏移;
    • 粘性定位以其最近的可滚动祖先和阈值为参考(如 top: 0)。

偏移规则要点:

  • 同时设置水平(leftright)或垂直(topbottom)两侧偏移且元素定宽/定高时,会在剩余空间中按约束进行分配。
  • 仅设置一个方向更直观;需要“拉伸”时才考虑两侧同时设置。

4. 相对定位(relative

特点:

  • 不脱离文档流(原位置仍占位)。
  • 通过偏移属性在原位置基础上“挪动”,不会影响其他元素的排布。
  • 常用于细微位置微调、为绝对定位子元素提供参考上下文。
html
<!-- 相对定位:微调位置 -->
<div class="card">
  <span class="badge">NEW</span>
</div>
css
.card {
  position: relative; /* 为内部绝对定位提供参考 */
  width: 240px;
  height: 120px;
  background: #f5f5f5;
}
.badge {
  position: relative; /* 相对定位,轻微上移右移 */
  top: -6px;
  left: 8px;
  background: #ff6b6b;
  color: #fff;
  padding: 2px 6px;
  border-radius: 4px;
}

5. 绝对定位(absolute

特点:

  • 脱离文档流,不再占据原来的空间。
  • 默认宽高为 auto,随内容收缩。
  • 偏移相对于“最近的定位祖先”的填充盒(无则相对于页面初始包含块)。
  • 常用于图标角标、气泡层、弹窗内元素的精确覆盖。
html
<!-- 绝对定位:角标与覆盖层 -->
<div class="card">
  <img class="cover" src="https://picsum.photos/240/120" alt="cover" />
  <span class="corner">HOT</span>
</div>
css
.card {
  position: relative; /* 提供包含块 */
  width: 240px;
  height: 120px;
}
.cover {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.corner {
  position: absolute;
  right: 8px;
  top: 8px;
  background: #ff6b6b;
  color: #fff;
  padding: 2px 6px;
  border-radius: 4px;
}

TIP

绝对定位的子元素不会撑开父元素高度。若父元素需要包含它们的高度,需显式设置父元素尺寸或通过其他布局方案实现。


6. 固定定位(fixed

特点:

  • 脱离文档流,固定在视口指定位置(除非受祖先创建的包含块影响)。
  • 常用于固定头部、返回顶部按钮、浮动工具条。
html
<!-- 固定定位:返回顶部按钮 -->
<button class="back-top">↑ TOP</button>
css
.back-top {
  position: fixed;
  right: 16px;
  bottom: 16px;
  padding: 8px 12px;
  background: #008c8c;
  color: #fff;
  border: none;
  border-radius: 6px;
  cursor: pointer;
}

TIP

移动端某些浏览器对 fixed 支持有差异;当祖先元素使用了 transform/filter 等属性时,固定元素可能会相对该祖先定位而非视口。


7. 粘性定位(sticky

特点:

  • 初始表现为相对定位,滚动到阈值后“吸附”在指定位置。
  • 常用于吸顶导航、分组标题吸附。
html
<!-- 粘性定位:吸顶导航 -->
<nav class="nav">导航</nav>
<section class="content">长内容……</section>
css
.nav {
  position: sticky;
  top: 0; /* 到达视口顶部时吸附 */
  background: #fff;
  border-bottom: 1px solid #eee;
  z-index: 10; /* 防止被内容覆盖 */
}
.content {
  height: 1500px;
}

8. 定位下的居中

  • 水平或垂直方向居中(适用于 absolute/fixed):
    1. 定宽(或定高);
    2. 将左右(或上下)距离设置为 0
    3. 将对应方向的 margin 设为 auto,自动吸收剩余空间。
html
<!-- 绝对定位:水平居中 -->
<div class="wrap">
  <div class="modal">对话框</div>
</div>
css
.wrap {
  position: relative;
  height: 240px;
  background: #f5f5f5;
}
.modal {
  position: absolute;
  width: 160px;
  left: 0;
  right: 0;
  margin-left: auto;
  margin-right: auto; /* 水平居中 */
  top: 24px;
  background: #fff;
  border: 1px solid #ddd;
  padding: 12px;
  border-radius: 8px;
}
  • 完全居中(更常用):
css
.center {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%); /* 不依赖定宽高 */
}

9. 多个定位元素重叠与层级

  • 层叠上下文:决定元素重叠顺序的规则集合。
  • z-index 控制层级,数值越大,元素越靠上;可以为负数(可能被常规流/浮动元素覆盖)。
  • 一般只有设置了 position 的元素使用 z-index 才有效;z-index 会创建新的层叠上下文。
css
.banner {
  position: relative;
}
.mask {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.3);
  z-index: 1;
}
.title {
  position: relative;
  z-index: 2;
}

TIP

有些属性也会创建层叠上下文(如 opacity < 1transformfilter 等)。当层级表现异常时,检查是否无意间创建了新的上下文。


10. 常见问题与最佳实践

  • 不要用绝对定位做通用布局:优先 Flex/Grid;绝对定位更适合覆盖/标注类元素。
  • 绝对/固定定位子元素不撑开父元素:若需要父容器自适应高度,请改用常规流或显式设置尺寸。
  • 合理设置包含块:需要相对父容器定位时,将父容器设为 position: relative
  • 注意移动端固定定位兼容性:必要时用 sticky 替代,或避免祖先使用 transform
  • 控制层级:仅在必要时设置 z-index,避免无序递增导致层级混乱。

11. 综合示例:角标与居中弹窗

html
<div class="card">
  <img class="cover" src="https://picsum.photos/320/180" alt="cover" />
  <span class="tag">SALE</span>
  <div class="dialog">Hello</div>
</div>
css
.card {
  position: relative;
  width: 320px;
  height: 180px;
}
.cover {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.tag {
  position: absolute;
  left: 8px;
  top: 8px;
  background: #ff6b6b;
  color: #fff;
  padding: 2px 6px;
  border-radius: 4px;
}
.dialog {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  background: #fff;
  padding: 12px;
  border-radius: 8px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);
}

12. 小结

  • relative:不脱流,微调位置/作为包含块参照。
  • absolute:脱流,相对最近定位祖先的填充盒偏移。
  • fixed:脱流,相对视口固定位置(可能受祖先影响)。
  • sticky:相对与固定的结合,适合吸顶/吸底场景。
  • 偏移围绕“包含块”计算;居中常用 translate(-50%, -50%) 技巧。

以上内容与常规流、浮动互补,形成完整的布局与叠加策略。