一直以来记错的CSS属性:Position 元素定位

最后更新:

我一直记忆的是 position:relative 是相对于父级元素定位的,今天才发现原来自己记错了。
也想明白了绝对定位的元素使用 margin:auto 为什么可以实现垂直居中

今天早上心有点静不下来,就去 SegmentFault 上看了看文章,有一篇文章 【“寒冬”三年经验前端面试总结之 CSS 篇】
里边的 垂直居中的方法四 我觉得挺奇怪的。

.outer {
  position: relative;
}
.inner {
  width: 100px;
  height: 100px;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;
}

为什么在 position:absolute 时,top,right,bottom,left 都为 0 时,使用 margin:auto 可以实现垂直居中。

是因为脱离文档流了还是因为别的?然后在群里讨论了下。

有些人说,absolute 之后变成行内块元素了,有些人说因为 margin

然后我又试了下 relativefixedsticky

只有 absolutefixed 这种脱离文档流的可以使用 margin:auto来居中。

设置了 leftright0 所以可以水平居中,topbottom0 可以使其垂直居中

归根结底是因为 margin:auto 填充了外部空间,然后定位是按照合模型最边界开始定位,即从 margin 开始。

box

另外还把自己一直以来记错的给掰了回来:

  • position:relative 是相对未定位前的元素自身来定位的。

我一直记忆的是相对于父级做定位。

以上

2019 年 11 月 20 日


2021年7月31日更新:

今天在写 数据大屏 “炫酷” 容器边框实现 的时候,突然发现 position:absolute 的定位起始点其实不是从定位祖先的左上角开始的,而是去除 border-width 的,小伙伴们请留意哦。

演示例子 🌰 CodePen link

顺便在补充一下,如果定位的值是百分比,那么这个百分比值是通过其 定位祖先content + padding 值来计算得出的,比如说:

.father{
  width: 1000px;
  height: 1000px;
  padding: 50px;
  border: 50px solid red;
  position: relative;
  box-sizing: content-box;  /* 默认盒模型 */
}
.sub{
  width: 100px;
  height: 100px;
  position: absolute;
  left: 10%; /* 等同于 left:110px */
}

为什么等于 left:20px?因为父级容器的 widthborder-areapadding-area 撑开了,但是不计算 border-area
所以 left = (contentWidth + paddingWidth*2) * 10% = (1000px + 50px*2) * 10% = 110px


如果把上边的例子的 .father 的盒模型改成 border-box 那么:left: 10% 就等于 left: 90px 了。

为何?

因为把和模型修改成 border-box 之后,CSS中设置的 width 就等于 border-area + padding-area + content-area 的总和,而因为 widthborder-widthpadding-width 是固定值,所以 content-area 就会被压缩。
所以在计算 left 百分比值时需要减去边框所占用的宽度,既是 left = (width - borderWidth*2) * 10% = (1000px - 50px*2) * 10% = 90px


参考

position - CSS(层叠样式表) | MDN
CSS 基础框盒模型介绍 - CSS(层叠样式表) | MDN