Застосування переходів CSS
Переходи CSS пропонують спосіб контролю швидкості анімації при зміні властивостей CSS. Замість негайного застосування змін властивості, можна змусити зміни властивості вступати в дію протягом певного проміжку часу. Наприклад, якщо змінити колір елемента з білого на чорний, зазвичай зміна є негайною. Коли ввімкнені переходи CSS, то зміни застосовуються в часових інтервалах, що відповідають кривій прискорення, і все це можна налаштувати.
Анімації, котрі залучають переходи між двома станами, нерідко звуть неявними переходами, адже стани у проміжку між початковим і фінальним станами визначаються браузером неявно.
Переходи CSS дають змогу вирішувати, котрі властивості анімувати (шляхом явного їх перелічення), коли анімація почнеться (шляхом задання затримки), як довго триватиме перехід (шляхом задання тривалості) та як перебігатиме перехід (шляхом задання функції пом'якшення, наприклад, лінійно, чи швидко на початку й повільно в кінці).
До яких властивостей CSS можна застосувати переходи?
Веброзробник може визначати, яка властивість буде анімована і як. Це дає змогу створювати складні переходи. Проте частина властивостей є неанімованими, адже їх немає змісту анімувати.
[!NOTE] Значення
auto
нерідко є дуже складним випадком. Специфікація радить не анімувати від і доauto
. Частина користувацьких агентів, як то засновані на Gecko, реалізовують цю вимогу, а інші, як то засновані на WebKit, є менш суворими. Використання анімацій зauto
може приводити до неочікуваних результатів, залежних від браузера та його версії, його слід уникати.
Визначення переходів
Переходи CSS контролюються за допомогою властивості-скорочення transition
. Це найкращий спосіб для налаштування переходів, адже він полегшує уникання несинхронізованих параметрів, на обтяжливе зневадження котрих можна витратити багато часу.
Контролювати окремі деталі переходу можна за допомогою наступних підвластивостей:
transition-property
Задає ім'я чи імена властивостей CSS, до яких застосовуються переходи. Лише перелічені тут властивості анімуються під час переходів; зміни решти властивостей відбуваються негайно, як зазвичай.
transition-duration
Задає тривалість, протягом якої відбуваються переходи. Можна задати одну тривалість, котра застосовується до всіх властивостей переходу, або декілька значень, аби дати змогу кожній властивості застосовуватися протягом інакшого проміжку часу.
transition-timing-function
Задає функцію, котра визначає, як обчислюються проміжні значення властивостей. Функції пом'якшення визначають, як обраховуються проміжні значення переходу. Більшість функцій пом'якшення можуть бути задані шляхом опису графіка відповідної функції, що задає чотири точки, по яких будується кубічна крива Безьє. Також можна обрати пом'якшення зі Шпаргалки функцій пом'якшення.
transition-delay
Визначає, скільки триватиме очікування між зміною властивості й фактичним початком переходу.
Скорочений синтаксис CSS transition
записується отак:
div {
transition: <property> <duration> <timing-function> <delay>;
}
Приклади
Базовий приклад
Цей приклад виконує чотирисекундну зміну розміру шрифту з двосекундною затримкою між часом, коли користувач навів курсор на елемент, і початком ефекту анімації:
#delay {
font-size: 14px;
transition-property: font-size;
transition-duration: 4s;
transition-delay: 2s;
}
#delay:hover {
font-size: 36px;
}
Приклад з кількома анімованими властивостями
CSS
.box {
border-style: solid;
border-width: 1px;
display: block;
width: 100px;
height: 100px;
background-color: #0000ff;
transition:
width 2s,
height 2s,
background-color 2s,
rotate 2s;
}
.box:hover {
background-color: #ffcccc;
width: 200px;
height: 200px;
rotate: 180deg;
}
Коли списки значень властивостей мають різну довжину
Якщо список значень будь-якої властивості коротший за інші, то її значення повторюються, поки довжини не будуть однакові. Наприклад:
div {
transition-property: opacity, left, top, height;
transition-duration: 3s, 5s;
}
Обробляється так, ніби це було:
div {
transition-property: opacity, left, top, height;
transition-duration: 3s, 5s, 3s, 5s;
}
Подібно до цього, якщо список значень певної властивості довший за довжину списку в transition-property
, він обрізається, тож якщо є такий CSS:
div {
transition-property: opacity, left;
transition-duration: 3s, 5s, 2s, 1s;
}
Він тлумачиться отак:
div {
transition-property: opacity, left;
transition-duration: 3s, 5s;
}
Застосування переходів для виділення меню
Поширене застосування CSS – для виділення елементів меню, на котрі користувач наводить мишею. Можна легко застосувати переходи, аби зробити ефект іще привабливішим.
По-перше, саме меню за допомогою HTML:
<nav>
<a href="#">Головна</a>
<a href="#">Про нас</a>
<a href="#">Контакти</a>
<a href="#">Посилання</a>
</nav>
Потім – CSS для реалізації вигляду й відчуття меню:
nav {
display: flex;
gap: 0.5rem;
}
a {
flex: 1;
background-color: #333;
color: #fff;
border: 1px solid;
padding: 0.5rem;
text-align: center;
text-decoration: none;
transition: all 0.5s ease-out;
}
a:hover,
a:focus {
background-color: #fff;
color: #333;
}
Такий CSS створює вигляд меню, колір і тла, і тексту якого змінюється, коли елемент перебуває в станах :hover
і :focus
:
Переходи display та content-visibility
Цей приклад демонструє те, як можна застосовувати переходи до властивостей display
та content-visibility
. Це корисно для створення анімацій входу-виходу, коли хочеться, наприклад, вилучити контейнер з DOM за допомогою display: none
, але зробити його зникнення плавним за допомогою opacity
, а не миттєвим.
Браузери, що це підтримують, виконують переходи display
та content-visibility
за допомогою варіації на дискретному типі анімації. Це, як правило, означає, що властивість перемикається між двома значеннями на 50% шляху анімації між ними.
Проте є виняток, а саме – коли анімується display: none
чи content-visibility: hidden
. У цьому випадку браузер перемикається між двома значеннями так, щоб перехідний вміст був видимим протягом усієї тривалості анімації.
Отже, наприклад:
- Коли
display
анімується відnone
доblock
(чи іншого видимого значенняdisplay
), значення перемикається наblock
на0%
тривалості анімації, щоб воно було видимим протягом усієї анімації. - Коли
display
анімується відblock
(чи іншого видимого значенняdisplay
) доnone
, значення перемикається наnone
на100%
тривалості анімації, щоб воно було видимим протягом усієї анімації.
На переходах за цими властивостями повинно бути задано transition-behavior: allow-discrete
. Фактично це вмикає переходи display
і content-visibility
.
Коли відбувається перехід за display
, необхідна директива @starting-style
, щоб задати на елементі стартові значення, від яких повинен початися перехід, коли елемент отримує перше оновлення стилю. Це потрібно для того, щоб уникнути неочікуваної поведінки. Усталено переходи CSS не запускаються при перших оновленнях стилів, уперше з'явившись у DOM, в тому числі при зміні значення display
з none
на якийсь інший стан. Анімації content-visibility
не потребують задання початкових значень у блоку @starting-style
. Це пов'язано з тим, що content-visibility
не приховує елемент з DOM, як це робить display
– він просто пропускає візуалізацію його вмісту.
HTML
HTML тут містить два елементи <p>
з <div>
між ними, котрий ми анімуємо від display
none
до block
.
<p>
Клацніть десь на екрані чи натисніть будь-яку клавішу, щоб перемкнути
<code><div></code> між прихованістю та показом.
</p>
<div>
Це елемент <code><div></code>, що переходить між
<code>display: none; opacity: 0</code> та
<code>display: block; opacity: 1</code>. Цікаво, чи не так?
</div>
<p>
Це інший абзац, потрібний для того, щоб показати, що
<code>display: none;</code> застосовується й вилучається до
<code><div> </code> вище. Якби змінювалася лише його
<code>opacity</code>, він завжди займав би місце в DOM.
</p>
CSS
html {
height: 100vh;
}
div {
font-size: 1.6rem;
padding: 20px;
border: 3px solid red;
border-radius: 20px;
width: 480px;
display: none;
opacity: 0;
transition:
opacity 1s,
display 1s allow-discrete;
/* Еквівалентно щодо
transition: all 1s allow-discrete; */
}
.showing {
opacity: 1;
display: block;
}
@starting-style {
.showing {
opacity: 0;
}
}
Зверніть увагу на те, що використовується блок @starting-style
, аби задати стартовий стиль для переходу, а також на включення властивості display
до списку переходу, зі значенням allow-discrete
.
JavaScript
Врешті-решт, додаймо трохи JavaScript, щоб налаштувати слухачі подій, які запускатимуть перехід (за допомогою класу showing
).
const divElem = document.querySelector("div");
const htmlElem = document.querySelector(":root");
htmlElem.addEventListener("click", showHide);
document.addEventListener("keydown", showHide);
function showHide() {
divElem.classList.toggle("showing");
}
Результат
Цей код візуалізується так:
Приклади JavaScript
[!NOTE] Особлива обережність необхідна, коли перехід застосовується відразу після:
- додавання елемента до DOM за допомогою
.appendChild()
- усунення властивості елемента
display: none;
.Це обробляється так, ніби початкового стану ніколи не було, натомість елемент завжди був у своєму фінальному стані. Легкий спосіб обійти це обмеження – застосувати
setTimeout()
зі жменею мілісекунд перед зміною властивості CSS, за якою необхідний перехід.
Застосування переходів для пом'якшення функціональності JavaScript
Переходи – чудовий інструмент, аби зробити речі куди плавнішими на вигляд, без потреби будь-що робити з функціональністю JavaScript. Про це – наступний приклад.
<p>Клацніть будь-де, аби перемістити м'яч</p>
<div id="foo" class="ball"></div>
За допомогою JavaScript можна реалізувати ефект руху м'яча до певного положення:
const f = document.getElementById("foo");
document.addEventListener(
"click",
(ev) => {
f.style.transform = `translateY(${ev.clientY - 25}px)`;
f.style.transform += `translateX(${ev.clientX - 25}px)`;
},
false,
);
За допомогою CSS такий рух можна без зайвих зусиль зробити плавним. Слід додати до елемента перехід, і будь-які зміни відбудуться плавно:
.ball {
border-radius: 25px;
width: 50px;
height: 50px;
background: #c00;
position: absolute;
top: 0;
left: 0;
transition: transform 1s;
}
Відстеження початку й завершення переходу
Подію transitionend
можна використати для відстеження того, що анімація завершила виконання. Це об'єкт TransitionEvent
котрий має на дві властивості більше, ніж типовий об'єкт Event
:
propertyName
Рядок, котрий вказує на ім'я властивості CSS, чий перехід завершився.
elapsedTime
Число з рухомою комою, котре вказує на число секунд, протягом якого відбувався перехід на мить спрацювання події. На це значення не впливає значення
transition-delay
.
Як зазвичай, для стеження за цією подією можна використати метод addEventListener()
:
el.addEventListener("transitionend", updateTransition, true);
Початок переходу відстежується за допомогою transitionrun
(спрацьовує до усіх затримок) і transitionstart
(спрацьовує після усіх затримок), в аналогічний спосіб:
el.addEventListener("transitionrun", signalStart, true);
el.addEventListener("transitionstart", signalStart, true);
[!NOTE] Подія
transitionend
не спрацьовує, якщо перехід переривається до свого завершення через те, що елемент ставdisplay: none
, чи те, що анімована властивість змінила своє значення.
Специфікації
Специфікація |
---|
CSS Transitions Level 2 (CSS Transitions 2) |
Дивіться також
- Інтерфейс
TransitionEvent
і подіяtransitionend
. - Застосування анімацій CSS