Пошаговые CSS-переходы

Влад Мержевич

Оригинал: css-tricks.com/staggered-css-transitions/
Перевод: Влад Мержевич

Допустим, вы хотите сдвинуть элемент при :hover для создания забавного визуального эффекта.

CSS

@media (hover: hover) {
  .list--item {
    transition: 0.1s;
    transform: translateY(10px);
  }
  .list--item:hover,
  .list--item:focus {
    transform: translateY(0);
  }
}

Классно! Но что если у вас есть несколько пунктов списка и вы хотите чтобы все они сдвигались при наведении, но каждый из них бы смещался пошагово по времени?

Хитрость заключается в transition-delay и применении разной задержки для каждого элемента. Давайте выберем каждый пункт списка по отдельности и применим к ним разные задержки. В данном случае мы выбираем вложенный <span> просто для удовольствия.

CSS

@media (hover: hover) {
  .list li a span {
    transform: translateY(100px);
    transition: 0.2s;
  }
  .list:hover span {
    transform: translateY(0);
  }
  .list li:nth-child(1) span {
    transition-delay: 0.0s;
  }
  .list li:nth-child(2) span {
    transition-delay: 0.05s;
  }
  .list li:nth-child(3) span {
    transition-delay: 0.1s;
  }
  .list li:nth-child(4) span {
    transition-delay: 0.15s;
  }
  .list li:nth-child(5) span {
    transition-delay: 0.2s;
  }
  .list li:nth-child(6) span {
    transition-delay: 0.25s;
  }
}

See the Pen Staggered Animations by Chris Coyier (@chriscoyier) on CodePen.

Если вы хотите дать себе чуть больше программистского контроля, то можете установить задержку как пользовательское свойство CSS.

CSS

@media (hover: hover) {
  .list {
    --delay: 0.05s;
  }
  .list li a span {
    transform: translateY(100px);
    transition: 0.2s;
  }
  .list:hover span {
    transform: translateY(0);
  }
  .list li:nth-child(1) span {
    transition-delay: calc(var(--delay) * 0);
  }
  .list li:nth-child(2) span {
    transition-delay: calc(var(--delay) * 1);
  }
  .list li:nth-child(3) span {
    transition-delay: calc(var(--delay) * 2);
  }
  .list li:nth-child(4) span {
    transition-delay: calc(var(--delay) * 3);
  }
  .list li:nth-child(5) span {
    transition-delay: calc(var(--delay) * 4);
  }
  .list li:nth-child(6) span {
    transition-delay: calc(var(--delay) * 5);
  }
}

Всё это может показаться немного капризным на ваш вкус. Скажем, ваш список вырастет, допустим, до семи или более пунктов и пошаговые переходы неожиданно перестанут работать для новых пунктов списка, поскольку здесь не учитывается их количество.

Так что при желании вы можете передать задержку из HTML.

HTML

<ul class="list">
  <li><a href="#0" style="--delay: 0.00s;">① <span>This</span></a></li>
  <li><a href="#0" style="--delay: 0.05s;">② <span>Little</span></a></li>
  <li><a href="#0" style="--delay: 0.10s;">③ <span>Piggy</span></a></li>
  <li><a href="#0" style="--delay: 0.15s;">④ <span>Went</span></a></li>
  <li><a href="#0" style="--delay: 0.20s;">⑤ <span>To</span></a></li>
  <li><a href="#0" style="--delay: 0.25s;">⑥ <span>Market</span></a></li>
</ul>

CSS

@media (hover: hover) {
  .list li a span {
    transform: translateY(100px);
    transition: 0.2s;
  }
  .list:hover span {
    transform: translateY(0);
    transition-delay: var(--delay); /* Берём из HTML */
  }
}

Или, если вы склоняетесь к Sass, то могли бы создать цикл с большим количеством пунктов, чем нужно в данный момент (зная, что дополнительный код довольно эффективно сожмётся).

SCSS

@media (hover: hover) {
  
  /* Основной стиль для :hover возьмите сверху */
  
  @for $i from 0 through 20 {
    .list li:nth-child(#{$i + 1}) span {
      transition-delay: 0.05s * $i;
    }
  }
}

Это может оказаться полезным, независимо от того, какой размер цикла вы выбираете.

Не выкладывайте свой код напрямую в комментариях, он отображается некорректно. Воспользуйтесь сервисом cssdeck.com или jsfiddle.net, сохраните код и в комментариях дайте на него ссылку. Так и результат сразу увидят.