CSS переходи: Last In, First Out

23

Від автора: у цьому уроці я розповім про мій улюблений трюк в CSS переходах — Last In, First Out.

CSS переходи: Last In, First OutCSS переходи: Last In, First Out

Введення

У додатках та на веб-сайтах інтерактивність і UX грають величезну роль в утриманні користувачів. CSS-анімація відкрила перед нами можливість поліпшення користувацького досвіду, але якщо трохи подумати, то можна зайти ще далі. У цьому уроці ми напишемо анімацію, яку я люблю називати «last in, first out», або по-іншому стек анімацію. Це означає, що при спрацьовуванні якого-небудь перемикача елементи починають рухатися в певній послідовності. При повторної активації перемикача елементи рухаються в зворотному порядку (щодо першої анімації). Я покажу, як зробити цей трюк за допомогою простих DIV ів, але тут важлива сама реалізація.

Візуальне подання

Щоб точніше зрозуміти, чого ми хочемо досягти, давайте розберемо весь процес по зображеннях. В нейтральному або базовому положенні всі наші діви – назвемо їх рядки займають фіксований простір. Нижче картинка:

CSS переходи: Last In, First Out

Уявіть, що ми натиснули на якийсь перемикач, і тепер нам необхідно, щоб наші рядки поступово розширювалися до 100%. Нижче візуальне подання цього моменту:

CSS переходи: Last In, First Out

Після завершення анімації всі рядки повинні займати всю ширину контейнера:

CSS переходи: Last In, First Out

Тепер при повторному натисканні на перемикач наші рядки повинні рухатися в зворотному напрямку. Нижня рядок завершує анімацію самої останньої, але в зворотному напрямку починає рух першої. Картинка:

CSS переходи: Last In, First Out

В кінці всі рядки повинні повернутися у вихідне положення, як показано на скріншоті нижче:

CSS переходи: Last In, First Out

Створюємо демо

Давайте створимо демо. Розмітка досить проста, складається з елемента c-bars і його дочірніх елементів c-bars__bar. Також у нас є перемикач, який буде додавати всіма рядками клас is-expanded. Нижче HTML код:

Toggle

1
2
3
4
5

JavaScript код для додавання класу дуже простий:

var btn = document.querySelector(‘.c-btn’);
var bars = document.querySelectorAll(‘.c-bars__bar’);
btn.addEventListener. (‘click’, function() {
for (var i = 0; i < bars.length; i++) {
bars.classList.toggle(‘is-expanded’);
}
});

У реальному прикладі скрипт може сильно відрізнятися. У нашому випадку суть в тому, що при натисканні кнопки до всіх рядків повинен додаватися клас is-expanded.

Базові стилі

Після розмітка необхідно додати стилі. У нашого контейнера буде рамка, а рядки будуть блочними елементами з початкової шириною. Ширина рядків задається для того, щоб ми могли задавати властивість transition від певної ширини до 100%. Нижче CSS:

.c-bars {
padding: 12px;
border: solid 4px #25b7a8;
}
.c-bars__bar {
display: block;
margin: 0 0 12px 0;
padding: 2px 0;
width: 24px;
color: #fff;
background-color: #25b7a8;
text-align: center;
transition: width 0.5 s;
}
.c-bars__bar:last-child {
margin-bottom: 0;
}

Як сказано вище, клас is-expanded додається при натисканні на кнопку. Тобто саме тут необхідно вказати інше значення ширини рядків:

.c-bars__bar.is-expanded {
width: 100%;
}

На даному етапі по кліку на кнопку спрацює анімація, і ширина всіх рядків буде плавно змінюватися від початкової ширини до 100%. Повторний клік поверне рядка в початкове положення.

Трюк 1 – Послідовні переходи

Зараз всі елементи, як при збільшенні ширини, так і при зменшенні ширини рухаються одночасно. Щоб зробити анімацію послідовної, необхідно задати властивість transition-delay. Відомо, що у нас 5 рядків. Задамо за допомогою nth-child кожному рядку затримку в 0.1 s. CSS код:

.c-bars__bar:nth-child(1) {
transition-delay: 0s;
}
.c-bars__bar:nth-child(2) {
transition-delay: 0.1 s;
}
.c-bars__bar:nth-child(3) {
transition-delay: 0.2 s;
}
.c-bars__bar:nth-child(4) {
transition-delay: 0.3 s;
}
.c-bars__bar:nth-child(5) {
transition-delay: 0.4 s;
}

Якщо натиснути на кнопку, то перший рядок починає рухатися відразу ж, а кожна наступна з затримкою в 0.1 s від попередньої. Відмінний ефект! Але якщо натиснути на кнопку ще раз, то ви помітите, що зворотна анімація йде в тому ж порядку, що і звичайна. Не зовсім те, що ми хочемо. Давайте поглянемо на другий трюк.

Трюк 2 — Last In, First Out

Щоб добитися ефекту анімації last in, first out, необхідно розглянути два стани рядків в демо. Перший стан – споконвічне, друге – розширене. Ми вже знаємо, як створити послідовну анімацію від початкового стану до розширеного. Коли всі рядки знаходяться в розширеному стані необхідно інвертувати значення transition-delay для кожного рядка. На щастя, зробити це досить просто.

При натисканні на кнопку елементів моментально додається клас is-expanded. Це означає, що під час анімації розширення даний клас присутня в кожному рядку. При повторному натисканні на кнопку даний клас негайно видаляється. Тобто ми можемо працювати з двома фазами:

Затримка анімації від початкового до розширеного стану застосовується до класу is-expanded.

А затримка від розширеного до початкового стану застосовується до базового класу.

Модифікований CSS:

.c-bars__bar:nth-child(1) {
transition-delay: 0.4 s;
}
.c-bars__bar.is-expanded:nth-child(1) {
transition-delay: 0s;
}
.c-bars__bar:nth-child(2) {
transition-delay: 0.3 s;
}
.c-bars__bar.is-expanded:nth-child(2) {
transition-delay: 0.1 s;
}
.c-bars__bar:nth-child(3) {
transition-delay: 0.2 s;
}
.c-bars__bar.is-expanded:nth-child(3) {
transition-delay: 0.2 s;
}
.c-bars__bar:nth-child(4) {
transition-delay: 0.1 s;
}
.c-bars__bar.is-expanded:nth-child(4) {
transition-delay: 0.3 s;
}
.c-bars__bar:nth-child(5) {
transition-delay: 0s;
}
.c-bars__bar.is-expanded:nth-child(5) {
transition-delay: 0.4 s;
}

Перевірте анімацію тепер. Ви успішно реалізували техніку last in, first out, і вона виглядає чудово.

Спрощення за допомогою Sass

В основі цього ефекту анімації лежить фундаментальна математична основа, а значить, тут нам може допомогти Sass (або будь препроцесор CSS з циклами і змінними). Блок Sass, документ, написаний вище CSS код, дуже простий:

$n: 5;
$delay: 0.1;
@for $i from 1 through $n {
$in: $delay * ($i — 1);
$out: $delay * ($n — $i);
.c-bars__bar:nth-child(#{$i}) {
transition-delay: #{$out}s;
}
.c-bars__bar.is-expanded:nth-child(#{$i}) {
transition-delay: #{$in}s;
}
}

Змінюючи значення $n (кількість рядків) і $delay (затримка анімації), можна повністю міняти анімацію

Висновок

Час підбивати підсумки! Тільки що ми розібрали простий, але дивовижний CSS приклад по створенню послідовної стек анімації. Кількість способів застосування даної техніки нескінченно. Якщо ви хочете подивитися мої приклади, то перейдіть на CSS Circle Menu.