Определение анимации ключевых кадров внутри медиа-запросов

Я пытаюсь получить объекты для "скольжения" в нижней части экрана, но поскольку я не могу получить высоту экрана в качестве единицы в CSS, я пытаюсь сделать это с помощью медиа-запросов, например так:

@media(max-height:500px) {
  @keyframe slideUp {
    0%    { transform: translate3d(0,500px,0); }
    100%  { transform: translate3d(0,0,0); }
  }
}
@media(max-height:750px) {
  @keyframe slideUp {
    0%    { transform: translate3d(0,750px,0); }
    100%  { transform: translate3d(0,0,0); }
  }
}
/* etc. */

Это не работает (он использует первую версию slideUp независимо от высоты), поэтому я предполагаю, что ключевые фреймы, однажды определенные, не могут быть перезаписаны или переназначены на основе медиа-запросов? Есть ли способ достичь этого эффекта (если у вас много разных настроек ключевого кадра и использование медиа-запроса для назначения соответствующего класса)?

Ответ 1

Я не понимаю, почему никто не предложил это, но вместо того, чтобы устанавливать ключевые кадры в запросе на медиа, вы можете настроить анимацию в запросе на медиа.

@media(max-height:500px) 
{
    #selectorGroup {
        animation: slideUp500 1s forwards;
    }
}

@media(max-height:750px) 
{
    #selectorGroup {
        animation: slideUp750 1s forwards;
    }
}


@keyframes slideUp500 {
    0%    { transform: translate3d(0,500px,0); }
    100%  { transform: translate3d(0,0,0); }
}

@keyframes slideUp750 {
    0%    { transform: translate3d(0,750px,0); }
    100%  { transform: translate3d(0,0,0); }
}

Ответ 2

Способ создания слайд-анимации, независимо от высоты экрана или элемента, заключается в использовании position: fixed:

.box {
    position: fixed;
    animation: slideUp 1s forwards;
}

@keyframes slideUp {
    from { top: 100%; }
    to { top: 0; }
}

Демо: http://jsfiddle.net/myajouri/Kvtd2/

Если вы хотите перемещаться относительно родительского элемента, а не окна просмотра, используйте вместо него position: absolute.

Ответ 3

Если вам нужно использовать translate3d, чтобы получить аппаратное ускорение на мобильных устройствах (как вы упомянули), и если вы не можете использовать at-rules внутри @media:

Вы можете определить один @keyframes с большим translateX (скажем 5000px) и изменить animation-duration на основе высоты экрана, чтобы скорость была более или менее одинаковой на разных высотах.

Я бы также определял диапазоны высоты (max-height и min-height) в отличие от верхних пределов (только max-height), чтобы предотвратить нежелательные переопределения стиля.

@keyframes slideUp {
    from { transform: translate3d(0,5000px,0); }
    to   { transform: translate3d(0,0,0); }
}

.box { animation: slideUp 5s forwards; }

@media (min-height: 0) and (max-height: 500px) {
    .box { animation-duration: 0.5s; }
}

@media (min-height: 501px) and (max-height: 750px) {
    .box { animation-duration: 0.75s; }
}

@media (min-height: 751px) and (max-height: 1000px) {
    .box { animation-duration: 1s; }
}

DEMO: http://jsfiddle.net/myajouri/9xLyf/

Ответ 4

С тех пор, как этот вопрос был задан. Но я вижу, что никто не ответил на решение, которое я дам вам, и это, на мой взгляд, проще, чем создавать разные media-queries для разных размеров экрана.

@myajouri предложил вам использовать fixed позицию, и вы отказались от этого решения, потому что вам нужно использовать 3d-преобразования, чтобы получить аппаратное ускорение. Но вы все равно можете использовать 3d-преобразования с фиксированной позицией. С помощью CSS преобразований, если вы используете проценты, они будут зависеть от размера самого элемента. Это позволит вам перемещать элемент за пределы экрана независимо от его размера, поэтому необходима только одна анимация ключевого кадра. Проверьте следующий фрагмент:

body {
  margin: 0;
  padding: 0;
}

.element {
  animation: slideUp 1s ease-in-out infinite alternate;
  background: #CCC;
  border: 5px solid gray;
  box-sizing: border-box;
  height: 100%;
  position: fixed;
  width: 100%;
}

@keyframes slideUp {
  from {
    transform: translate3d(0, 100%, 0);
  }
  to {
    transform: translate3d(0, 0, 0);
  }
}
<div class="element" />