Пошагові 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;
  }
}

Якщо ви хочете мати більше програмістського контролю, можете встановити затримку як користувацьку 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;
    }
  }
}

Це може бути корисним незалежно від того, який розмір цикла ви обираєте.

Часті запитання