Для чего нужен перевод (-50%) для центрирования элемента, который находится сверху: 50%?

Я вижу, что этот код работает, чтобы выровнять div по вертикали внутри его родительского элемента:

.element {
  position: relative;
  top: 50%;
  transform: translateY(-50%);
}

Вопрос в том, почему? Моя первая мысль заключалась в том, что родительский элемент охватывает больше, чем область просмотра. Я сделал родительскую высоту просмотра равным 100vh и ширину 100%. Это не сработало. Мне все еще нужен перевод или отрицательное смещение. Зачем мне нужно отрицательное смещение, если для родительского элемента установлено значение margin: 0;? Это из-за вычисленной разницы, которую я не учитываю?

Ответ 1

top: 0 (по умолчанию)

По умолчанию ваш элемент находится в верхней части страницы, а верхняя часть элемента равна 0:

--------Top of Page--------
{element}


------Middle of  Page------



------Bottom of  Page------

верх: 50%

Когда вы перемещаете его на 50% высоты (50% от всей страницы), верхняя часть элемента находится на отметке 50%, то есть элемент начинается с 50% и не центрируется.

--------Top of Page--------



------Middle of  Page------
{element}


------Bottom of  Page------

верх: 50%; преобразования: translateY (-50%);

Когда вершина элемента находится на полпути, мы можем переместить элемент на половину своей высоты, чтобы сосредоточить его на всей странице. То, что делает transform:translateY(-50%);:

--------Top of Page--------



{element}-Middle of Page---



------Bottom of  Page------

Но почему мы не можем просто сказать top: 25% или что-то в этом роде? Я сделал быстрый фрагмент, чтобы показать вам разницу с этой реализацией:

body {
  margin: 0;
}
.row {
  display: flex;
  justify-content: space-between;
}
.container {
  display: inline-block;
  margin: 5px;
  width: 200px;
  height: 200px;
  background: tomato;
}
.inner {
  position: relative;
  margin: 0 auto;
  height: 50%;
  width: 50%;
  background: #FFC4BA;
}
.inner.small {
  width: 25%;
  height: 25%;
}
.inner.big {
  width: 75%;
  height: 75%;
}
.percent {
  top: 25%
}
.transform {
  top: 50%;
  transform: translateY(-50%);
}
<b>First row </b>looks alright, but that because the gap works well with the 25%
<div class="row">
  <div class="container">
    <div class="inner percent"></div>
  </div>
  <div class="container">
    <div class="inner transform"></div>
  </div>
</div>
<b>Second row </b>made the center square a bit smaller, and the 25% now is too high as we'd expect the bottom of the element to reach 75%
<div class="row">
  <div class="container">
    <div class="small inner percent"></div>
  </div>
  <div class="container">
    <div class="small inner transform"></div>
  </div>
</div>
<b>Third row </b>now I've made the center box big and it ends lower than 75% making 25% start too late
<div class="row">
  <div class="container">
    <div class="big inner percent"></div>
  </div>
  <div class="container">
    <div class="big inner transform"></div>
  </div>
</div>

Ответ 2

В то время как другие ответили, что -50 перемещает внутренний элемент на половину собственной высоты, я подумал, что эта небольшая анимация, показывающая движение до top: 50%;, а затем transform: translateY(-50%); second, может помочь.

@keyframes centerMe {
  0% { top: 0%; transform: translateY(0%); }
  50% { top: 50%; transform: translateY(0%); }
  100% { top: 50%; transform: translateY(-50%); }
}

.outer {
  position: relative;
  border: solid 1px;
  height: 200px;
  width: 200px;
}

.inner {
  position: relative;
  background-color: red;
  height: 50px; width: 50px;
  margin: auto;
  animation: centerMe 5s;
  animation-fill-mode: forwards;
}

/* rules for example */
.hline,.vline{background:#000;position:absolute}.vline{height:100%;width:1px;left:calc(50% - .5px);top:0}.hline{width:100%;height:1px;top:calc(50% - .5px)}
<div class="outer">
  <div class="hline"></div>
  <div class="vline"></div>
  <div class="inner"></div>  
</div>

Ответ 3

position: relative;
top: 50%;

... перемещает элемент на расстояние, равное половине высоты родителя.

Поскольку позиция по умолчанию помещает верхнюю часть внутреннего элемента в верхнюю часть внешнего элемента, это помещает верхнюю часть внутреннего элемента в середину внешнего элемента.

transform: translateY(-50%);

Это перемещает внутренний элемент обратно на половину высоты внутреннего элемента.

Сочетание их ставит середину внутреннего элемента в середину родительского элемента.

Ответ 4

Почему для 50% -ного значения требуется сдвиг перевода -50%?

Вместо того, чтобы напрямую отвечать на этот вопрос, я собираюсь ответить на более общий вопрос:

Как работает привязка позиции в CSS?

Надеюсь, что, отвечая на вопрос в целом, вы поймете те части, которые применимы к вашему конкретному случаю.


Что вы подразумеваете под "фиксацией позиции"?

Закрепление позиций - это когда DOM node позиционируется таким образом, что он привязан к его родительскому элементу в данном измерении. Если левая верхняя часть node привязана к верхнему левому краю своего родителя, узлы останутся выровненными в верхнем левом углу независимо от размера любого элемента.

Как выглядит привязка позиции?

Я собираюсь использовать шаблон для всех дальнейших примеров, поэтому важно понять базовый пример.

.container {
  background-image: -webkit-linear-gradient(left, darkred 0, darkred 50%, goldenrod 50%, goldenrod 100%), -webkit-linear-gradient(left, darkgreen 0, darkgreen 50%, darkblue 50%, darkblue 100%);
  background-image: linear-gradient(to right, darkred 0, darkred 50%, goldenrod 50%, goldenrod 100%), linear-gradient(to right, darkgreen 0, darkgreen 50%, darkblue 50%, darkblue 100%);
  background-position: top, bottom;
  background-repeat: no-repeat;
  background-size: 100% 50.1%, 100% 50.1%;
  height: 70vh;
  margin: 15vh 15vw;
  position: relative;
  width: 70vw;
}
.box {
  background-image: -webkit-linear-gradient(left, red 0, red 50%, yellow 50%, yellow 100%), -webkit-linear-gradient(left, green 0, green 50%, blue 50%, blue 100%);
  background-image: linear-gradient(to right, red 0, red 50%, yellow 50%, yellow 100%), linear-gradient(to right, green 0, green 50%, blue 50%, blue 100%);
  background-position: top, bottom;
  background-repeat: no-repeat;
  background-size: 100% 50.1%, 100% 50.1%;
  height: 50vmin;
  position: absolute;
  width: 50vmin;
}
<div class="container">
  <div class="box"></div>
</div>