Как убрать рывки при анимации и сделать ее плавной?

Почему в моему случае анимация элемента происходит "рывками"? Как это исправить?

.block {
  width: 200px;
  height: 200px;
  background: yellow;
  border: 1px dashed black;
  display: flex;
  align-items: center;
  margin-top: 100px;
  position: relative;
  animation: blocks 2s ease-in-out infinite;
}

.block_child {
  width: 100px;
  height: 100px;
  background: purple;
  border: 2px double white;
}

@keyframes blocks {
  0% {
    top: 0px;
  }
  100% {
   bottom: 100px;
  }
}
<div class="block">
  <div class="block_child"></div>
</div>


Ответы (1 шт):

Автор решения: Vasily

Для того что бы анимировать позицию лучше использовать свойство transform вместо top и bottom, поскольку это позволит задействовать GPU что сделает возможным перемещение элемента на суб-пиксельном уровне, т.е более плавно:

// в одну сторону
@keyframes blocks {
  100% {
   transform: translateY(calc(100% - 100px));
   // не доходя 100px до нижнего края
  }
}

// в обе стороны
@keyframes blocks {
  50% {
   transform: translateY(calc(100% - 100px));
  }
  100% {
   transform: translateY(0);
  }
}

Рабочие примеры на основе Вашего кода:

В ОДНУ СТОРОНУ (как у Вас было)

.block {
  width: 200px;
  height: 200px;
  background: yellow;
  border: 1px dashed black;
  display: flex;
  align-items: center;
  position: relative;
  animation: blocks 2s ease-in-out infinite;
}

.block_child {
  width: 100px;
  height: 100px;
  background: purple;
  border: 2px double white;
}

@keyframes blocks {
  100% {
   transform: translateY(calc(100% - 100px));
  }
}
<div class="block">
  <div class="block_child"></div>
</div>

В ОБЕ СТОРОНЫ

.block {
  width: 200px;
  height: 200px;
  background: yellow;
  border: 1px dashed black;
  display: flex;
  align-items: center;
  position: relative;
  animation: blocks 4s ease-in-out infinite;
}

.block_child {
  width: 100px;
  height: 100px;
  background: purple;
  border: 2px double white;
}

@keyframes blocks {
  50% {
   transform: translateY(calc(100% - 100px));
  }
  100% {
   transform: translateY(0);
  }
}
<div class="block">
  <div class="block_child"></div>
</div>

В вашем варианте Вы делали одновременно top и bottom, вместо того что бы делать что то одно, поэтому как таковой анимации не происходило.

→ Ссылка