top: 50%;实际上对相对定位的元素做了什么?

What does top: 50%; actually do on relatively positioned elements?

一段时间以来,我一直在使用相对定位的元素将事物垂直居中。不过,我从来不明白,为什么 position: relative; top: 50%; 不将元素垂直居中, 至少将元素的顶部边缘居中放置在其容器 div 中。

position: relative 根据 MDN:

lays out all elements as though the element were not positioned, and then adjusts the element's position, without changing layout

top关键字:

specifies the amount the element is moved below its normal position.

以及 top 关键字的 % 值:

Is a percentage of the containing block's height

所以一个值为 top: 50% 的相对定位元素应该向下移动包含块高度的 50%,对吗?这是否意味着该元素的上边缘恰好位于包含元素的中间?

考虑这个片段:

.container {
  overflow: hidden;
  width: 90%;
  height: 90%;
  margin: 0 auto;
  background-color: #eee;
}
.child {
  width: 40%;
  height: 40%;
  margin: 0 auto;
  background-color: #444;
  border-top: 5px solid #f00;
}
.top-50-percent {
  position: relative;
  top: 50%;
}

.contract-and-expand {
  animation-name: contract-and-expand;
  animation-duration: 5s;
  animation-iteration-count: infinite;
  animation-timing-function: ease-in-out;
}
@keyframes contract-and-expand {
  50% {
    height: 0%;
  }
}
<html>
  <head>
    <style>
      /* Just initial/basic CSS rules here to make this look better */
      
      @import url("https://necolas.github.io/normalize.css/latest/normalize.css");

      * {
        box-sizing: border-box;
        margin: 0;
      }
      html, body {
        height: 100%;
      }
      body {
        color: #aaa;
      }
      .center-vertically {
        position: relative;
        top: 50%;
        transform: translateY( -50% );
      }
      p {
        position: absolute; /* Remove paragraphs from flow so they don't interfere */
      }
    </style>
  </head>
  <body>
    <div class="container center-vertically contract-and-expand">
      <p>Container Wrapper</p> <!-- Paragraphs are removed from the flow -->
      
      <div class="child top-50-percent">
      </div>
      
    </div>
  </body>
</html>

从代码片段来看,上边缘似乎居中。这总是正确的吗?有这样类似的fiddle:https://jsfiddle.net/9kyjt8ze/5/ 当视口的高度被拉高时,子元素的上边框看起来不再居中。

我用 Inkscape 和 2 个(黄色)垂直块进行了测量,尺寸完全相同。这是一种视错觉。在 fiddle 中,顶部边缘实际上从未偏离中心。此外,我的所有假设似乎都是正确的:相对定位的元素上的 top:50% 将该元素的上边框向下移动了容器高度的 50%。这不能完全垂直居中元素的原因是 顶边 是在相对定位的元素上使用 top: 50% 时的枢轴点。