Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «CSS властивості для створення анімацій та плавних перехідних ефектів». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**CSS-анімації та переходи** - два інструменти для руху на сторінці. `transition` реагує на зміну стану; `animation` з `@keyframes` запускається сама і може зациклюватись. ```css .btn { transition: transform 0.2s ease; } .btn:hover { transform: scale(1.04); } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } .el { animation: fadeIn 0.3s ease-out forwards; } ``` **Головне правило:** анімуй `transform` і `opacity` - вони не перераховують layout і працюють на GPU.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**CSS-анімації та переходи** - це два окремі інструменти для додавання руху на сторінку, і вони вирішують різні задачі. ## Теорія ### TL;DR - `transition` реагує на зміну стану (hover, focus, toggle класу) і чекає тригера - `animation` з `@keyframes` запускається сама - тригер не потрібен, може зациклюватись, може йти у зворотному напрямку - Головна різниця: `transition` - це перехід А до Б; `animation` - це сценарій з довільною кількістю кроків - Для продуктивності анімуй `transform` і `opacity` - вони працюють на GPU і не перераховують layout - Анімація `width`, `height`, `top`, `left` викликає reflow на кожному кадрі - замінюй на `transform` ### Швидкий приклад ```css /* transition: реагує на :hover */ .button { background: #3b82f6; transition: background 0.3s ease, transform 0.15s ease; } .button:hover { background: #1d4ed8; transform: scale(1.04); } /* animation: запускається сама, тригер не потрібен */ @keyframes fadeIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } } .modal { animation: fadeIn 0.25s ease-out forwards; } ``` `transition` чекає. `animation` просто йде. ### transition: зміни за тригером `transition` приймає чотири значення: яку властивість анімувати, скільки часу, яке пом'якшення, і необов'язкова затримка. Кілька властивостей розділяються комами: ```css .card { transition: box-shadow 0.2s ease, transform 0.2s ease; } .card:hover { box-shadow: 0 8px 24px rgba(0,0,0,0.15); transform: translateY(-4px); } ``` `transition: all 0.3s` технічно працює. Але коли пізніше додаєш нову властивість і вона раптово починає анімуватись, витратиш час на дебаг. Краще перелічувати властивості явно. Функції пом'якшення (timing function): `ease` - стандарт, починає швидко і гальмує наприкінці. `linear` - рівна швидкість. `ease-out` - гальмує до кінця, найприродніше відчувається для UI-взаємодій, бо нагадує як зупиняються фізичні об'єкти. `cubic-bezier()` - повний контроль над кривою. ### animation + @keyframes: сценарна анімація `@keyframes` описує анімацію як послідовність знімків. `from/to` - те саме що `0%/100%`, але можна ставити відсоткові точки де завгодно: ```css @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.08); } 100% { transform: scale(1); } } .badge { animation: pulse 1.5s ease-in-out infinite; } ``` Основні властивості `animation`: - `animation-name` - який блок `@keyframes` використовувати - `animation-duration` - тривалість одного циклу - `animation-timing-function` - пом'якшення (ті самі варіанти що в transition) - `animation-delay` - затримка перед першим запуском - `animation-iteration-count` - `1`, `3`, або `infinite` - `animation-direction` - `normal`, `reverse`, `alternate` (туди і назад) - `animation-fill-mode` - який стан тримати до або після програвання `animation-fill-mode: forwards` варто запам'ятати окремо. Без нього елемент повертається до початкового вигляду щойно анімація закінчується. Це ламає більшість ефектів появи (fade-in). ### Що анімувати для продуктивності Браузер малює сторінку шарами. Зміни `transform` і `opacity` відбуваються на compositor thread - окремому процесі, який не торкається розрахунку layout. Всі інші властивості (`width`, `height`, `padding`, `left`, `top`) змушують браузер перераховувати геометрію або перемальовувати пікселі. ```css /* викликає reflow на кожному кадрі - повільно */ .bad { transition: width 0.3s ease; } /* залишається на compositor thread - швидко */ .good { transition: transform 0.3s ease; } ``` Якщо потрібно анімувати ріст елемента - використовуй `transform: scaleX()` або `scaleY()` замість `width` чи `height`. Для виїзду елемента - `transform: translateX()` замість `left`. `will-change: transform` підказує браузеру заздалегідь виділити окремий compositor layer для елемента. З практики: додавати `will-change` усюди підряд - часта помилка оптимізації. Спочатку профілюй, потім додавай тільки там де реально є просідання кадрів. Кожен promoted layer займає пам'ять GPU. ### Типові помилки **Анімація layout-властивостей.** Зміна `height` або `width` у циклі дропає кадри. Для розширення елементів - `transform: scaleY()`. **`transition: all`.** Працює, але анімує непотрібні властивості. Перелічуй явно. **Забутий `animation-fill-mode: forwards`.** Елемент красиво з'являється, потім стрибає назад до `opacity: 0`. Додай `forwards` - елемент залишиться в кінцевому стані. **`@keyframes` для hover-ефектів.** Hover - це два стани, саме для цього є `transition`. `@keyframes` має сенс коли потрібно три і більше кроків, або коли анімація запускається без дії користувача. **Відсутня підтримка `prefers-reduced-motion`.** Частина користувачів має вестибулярні порушення і анімація викликає дискомфорт. Невеликий медіа-запит вирішує це: ```css @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; } } ``` ### Питання на співбесіді **Q:** Які CSS-властивості безпечно анімувати з точки зору продуктивності? **A:** `transform` і `opacity`. Вони працюють на compositor thread і не викликають layout чи repaint. Властивості `width`, `height`, `top`, `left` запускають reflow на кожному кадрі. **Q:** Що робить `animation-fill-mode: forwards`? **A:** Каже елементу зберігати стилі з останнього keyframe після завершення анімації. Без цього елемент повертається до початкового вигляду щойно анімація зупиняється. **Q:** Чи можна запустити кілька анімацій на одному елементі? **A:** Так, через кому: `animation: fadeIn 0.3s ease, pulse 1s ease-in-out 0.3s infinite`. Кожна анімація має власний тайминг і вони перекриваються незалежно. **Q:** Коли `transition` не спрацює? **A:** На властивостях без проміжних значень. Перехід між `display: none` і `display: block` неможливий - немає середнього стану. Для показу/приховування анімують `opacity` разом з `visibility`, або використовують `transform: scale(0)`. **Q:** Яка різниця між `animation-direction: alternate` і двома окремими блоками `@keyframes`? **A:** `alternate` автоматично реверсує анімацію на непарних ітераціях з тим самим пом'якшенням. Два окремих блоки дають незалежний контроль над кривими - зручно коли потрібен повільний ease-out в одну сторону і різкий snap у зворотну. ## Приклади ### Hover-кнопка з transition ```css .btn { background: #3b82f6; color: white; padding: 10px 20px; border: none; border-radius: 6px; cursor: pointer; /* дві властивості з різним таймингом */ transition: background 0.25s ease, transform 0.15s ease; } .btn:hover { background: #2563eb; transform: scale(1.03); } .btn:active { transform: scale(0.97); /* зворотний зв'язок на клік */ } ``` `background` займає 0.25s, а `transform` реагує за 0.15s. Різниця в часі відчувається природніше ніж однакова швидкість для обох: масштаб клацає чітко, а колір слідує за ним. ### Спінер завантаження з animation ```css @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } .spinner { width: 24px; height: 24px; border: 3px solid #e5e7eb; border-top-color: #3b82f6; border-radius: 50%; animation: spin 0.75s linear infinite; } ``` Тут правильний вибір - `linear`. Спінер з `ease` розганяється і гальмує на кожному оберті, виглядає наче бореться сам з собою. Рівномірна швидкість - те що потрібно.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.