Как сделать ступенчатую анимацию при наведении курсора на чистом CSS

HTML/CSS
2948
Как сделать ступенчатую анимацию при наведении курсора на чистом CSS
Active vision

Предположим, вы хотите сделать красивый визуальный эффект и как-то переместить элемент при наведении курсора (:hover).


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

Это очень круто. Но что, если у вас список из нескольких элементов, и вы хотите, чтобы все они анимировались при наведении курсора? И не все сразу, а постепенно, то есть создать некую ступенчатую анимацию.

Анимация при наведении курсора

Мы выполним эту задачу без использования JavaScript, на простом CSS. Весь трюк заключается в свойстве transition-delay и применении разной задержки к каждому элементу. Давайте создадим анимацию при наведении курсора — выделим каждый элемент списка по отдельности для этого выберем простой span.


HTML
<ul class="list">
  <li><a href="#0"> ① <span>Раз</span></a></li>
  <li><a href="#0"> ② <span>Два</span></a></li>
  <li><a href="#0"> ③ <span>Три</span></a></li>
  <li><a href="#0"> ④ <span>Четыре</span></a></li>
  <li><a href="#0"> ⑤ <span>Четыре</span></a></li>
  <li><a href="#0"> ⑥ <span>Пять</span></a></li>
</ul>

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;
  }
}

Если вы хотите больше свободы, вы можете задать transition-delay как 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);
  }
}

Это, скажем так, на ваш вкус. А что, если ваш список начинают расти, возможно, до семи или более пунктов. Наш эффект уже не работает на новых элементах списка, потому этот код их просто не учитывает.

Но, мы можем передавать --delay из 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, вы можете создать цикл с бОльшим количеством элементов, чем вам сейчас нужно, например 20:


SCSS
@media (hover: hover) {
  @for $i from 0 through 20 {
    .list li:nth-child(#1) span {
      transition-delay: 0.05s * $i;
    }
  }
}