写页面时经常遇到这些需求:小角标要贴在卡片右上角、导航栏要固定在页面顶部、弹窗要盖在屏幕正中间。这些都靠 position 实现。这篇讲清楚 static、relative、absolute、fixed 四种定位方式的区别,以及最常用的搭配套路。

static:默认值,先从它说起

每个元素默认都是 static,也就是按文档流从上往下排,谁也不特殊。static 元素设置 top、left 这些偏移属性是完全无效的——想让元素挪位置,第一步先把 position 换掉。

relative:相对自己原来的位置挪

.tip {
  position: relative;
  top: 10px;    /* 向下挪 10px */
  left: 20px;   /* 向右挪 20px */
}

两个要点:top 是「往下挪」,想往上要写负值;元素挪走了,原来占的位置还留着,后面的元素不会补上来。

relative 更重要的角色是当定位参照物——下一节的 absolute 就靠它。

absolute:相对最近的定位祖先

absolute 让元素脱离文档流,相对「最近的非 static 祖先」定位。最经典的场景是角标:

<div class="card">
  <span class="badge">新</span>
</div>
.card {
  position: relative;   /* 给子元素当参照物 */
  width: 200px;
  height: 100px;
}
.badge {
  position: absolute;
  top: 8px;
  right: 8px;           /* 贴在卡片右上角 */
}

注意父级一定要加 position: relative,这招俗称「子绝父相」。如果父级全都没有定位,absolute 元素会一直往外层找,最后相对整个页面定位——角标飞到天边去,多半就是这个原因。

fixed:相对浏览器窗口,滚动也不动

.navbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;      /* 左右拉满 */
  height: 50px;
}

fixed 同样脱离文档流,后面的内容会顶到导航栏底下,记得给 body 加个 padding-top: 50px 补偿空缺。

组合技:绝对定位居中

弹窗居中是定位最经典的用法:

.dialog {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

先把元素的左上角放到屏幕正中,再往回挪自己宽高的一半,弹窗无论多大都精确居中。

另外,absolute 和 fixed 元素重叠时,默认是写在后面的盖住写在前面;想手动控制层级,就给元素加 z-index,数值大的在上层:

.dialog { z-index: 100; }   /* 弹窗盖住普通角标 */

小结

  • static 是默认值,设置偏移无效
  • relative 相对自身偏移、原位置仍占位,主要用来当参照物
  • absolute 相对最近的定位祖先,「子绝父相」是最常见搭配
  • fixed 相对浏览器窗口,滚动不动,记得补偿文档流空缺
  • top/left 的参照物是定位祖先而不是浏览器,位置不对先查参照物

把这篇和之前的 Flexbox、Grid 放在一起用,常见的布局需求基本都能拿下了。