定位 = 元素相对「谁」偏移。五种 position 的区别就在参考系

① 五种 position

static(默认):top/left 完全无效 relative:偏移后仍占原位(原空间保留) absolute:贴着 .stage 右下角
inset: 12px 12px 12px 60%
值参考系是否脱离文档流典型用途
static—否默认
relative自身正常位置否(留位)给子绝对定位当锚点、微调图标
absolute最近的已定位祖先是徽标、下拉、遮罩
fixed视口(有 transform/filter 的祖先会改变它)是吸底按钮、对话框
sticky滚动容器 + 自身所在轨道/区块范围否表格表头、分区标题、吸附导航

sticky 失效的三大原因:没写 top 等偏移、某个祖先有 overflow: hidden(改变了滚动容器)、父容器高度不足以容纳滑动范围。

② inset 简写与三种绝对居中

.pop { inset: 8px 12px auto auto; }   /* = top right bottom left,顺序与 margin 一致 */
/* 居中方式一:网格(推荐) */ .wrap { display: grid; place-items: center; }
/* 居中方式二:transform */ .m { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
/* 居中方式三:inset + auto margin(需固定宽高) */ .m { position: absolute; inset: 0; margin: auto; width: 120px; height: 40px; }
transform 居中inset+auto

③ z-index 不起作用?因为它在别人的上下文里

不设 z-index(auto,按 DOM 顺序,后面在上)
z-index: 1
z-index: 3 → 最高
父级有 z-index: 1 或 isolation: isolate → 形成层叠上下文
子的 z-index: 999 只在父上下文内部比大小
外部兄弟 z-index: 2 就能盖住那个 999

创建层叠上下文的条件(任一即成立):position 非 static 且 z-index 非 auto、opacity < 1、transform/filter/backdrop-filter/perspective/mask、will-change、isolation: isolate、position: fixed、Flex/Grid 子项的 z-index 非 auto、@layer 不参与(层叠上下文与层叠层级是两件事)。

/* 排错顺序:① 找到最近的层叠上下文祖先;② 只在这一层里比 z-index;
   ③ 需要「跳出」就给祖先去掉 transform/filter 或把浮层用 position:fixed 挂到 body 层。
   数值别用 9999/999999 —— 建一套自己的刻度:10 下拉、50 遮罩、100 对话框、200 toast。 */

④ fixed:滚动时钉在视口(在本示例里是 iframe 的视口)

右下角紫色块是 position: fixed。滚动本页面它会一直停在那里 —— 但注意祖先一旦有 transform/filter/will-change,fixed 的参考系就变成那个祖先,这是「弹窗跟着页面乱跑」的常见原因。

fixed 角标

⑤ sticky 吸附表头/导航

往下滚,这条栏会停在容器顶。它属于 .scroll 这个滚动容器,所以吸附范围仅限这个盒子的高度。

真实站点里 top 常要写成 var(--header-h),避免被吸顶页头盖住。

表格的 <thead> 也能 sticky,但需要 border-collapse: separate(合并边框模式下边框不会跟随)。

⑥ 实战:下拉菜单与徽标

.badge-wrap { position: relative; }             /* 锚点 */
.badge { position: absolute; top: -6px; right: -6px; }  /* 相对锚点偏移 */

弹出层靠近视口边缘会被裁掉时,用 position: fixed + @popper/anchor()(仍在演进)或干脆换用原生 <popover> + position-area,见 HTML 教程第十三章与本站锚点章节。

⑦ 自查清单

  1. 「absolute 跑到页面左上角」→ 忘了给祖先写 position: relative。
  2. 「sticky 不吸附」→ 查祖先 overflow、查有没有 top。
  3. 「z-index 无效」→ 先确认两个元素在同一个层叠上下文里。
  4. 「fixed 弹窗跟着滚动」→ 祖先有 transform/filter/perspective。
  5. 「定位元素挡住了下文却看不见」→ 它脱离了流,父容器高度不含它,需要额外 padding 或改用 Grid 叠层。