Ось готовий урок, написаний у стилі лекцій CS50, адаптований під тему CSS Animations.
🎬 Урок: Animations та @keyframes
(Як вдихнути життя у статичний веб)
1. 🔥 Вступ: проблема та мотивація
Уявіть, що ви прийшли в театр. Ви сідаєте в крісло, відкривається завіса... і ви бачите акторів, які стоять нерухомо, як статуї. Потім світло гасне на секунду — БАХ! — і вони вже стоять в інших позах. Ще раз світло гасне — БАХ! — і головний герой вже "мертвий" на підлозі.
Чи зрозуміли ви сюжет? Напевно. Чи сподобалось вам це? Навряд чи. Це виглядає смикано, неприродно і дешево.
На жаль, саме так виглядає вебсторінка без анімацій. Елементи просто "телепортуються": була кнопка сіра — стала червона. Меню не було — хоп, і воно перекрило екран.
У реальному світі речі не телепортуються. Якщо я кину вам маркер, він летить через простір, він має швидкість, він сповільнюється, коли потрапляє вам у руку.
Питання до вас: Чому ж тоді ми змушуємо користувачів терпіти ці "телепортації" в інтерфейсах?
Сьогодні ми виправимо це. Ми навчимося не просто змінювати стилі, а режисерувати зміни в часі. Ми перетворимо "слайд-шоу" на "кіно". Ласкаво просимо у світ Animations та Keyframes.
2. 🧠 Теоретична база (без сухої академічності)
Щоб створити магію руху в CSS, нам потрібні дві речі. Уявіть це як зйомку сцени у фільмі:
- Сценарій (
@keyframes): Що саме має відбуватися? - Команда "Мотор!" (
animation): Який актор це грає, як довго і в якому стилі?
📜 1. Сценарій: @keyframes
Браузер — дуже розумний, але ледачий художник. Йому не треба малювати кожен міліметр руху. Ви даєте йому лише ключові кадри (звідси й назва keyframes):
- 0% (from): Початковий стан.
- 100% (to): Кінцевий стан.
Браузер сам домалює все, що між ними (це називається інтерполяція).
🎬 2. Властивість animation
Просто написати сценарій мало. Він може лежати в столі. Треба призначити його конкретному елементу (наприклад, кнопці) і сказати: "Грай цю роль 2 секунди!".
Що треба знати залізно (Minimum Viable Knowledge):
1. animation-name: Ім'я вашого сценарію (@keyframes).
2. animation-duration: Скільки часу триває "вистава" (наприклад, 2s або 500ms). Без цього анімація не спрацює!
Що працює "під капотом"? Браузер бере ваші точки (наприклад, прозорість 0 і прозорість 1) і ділить час (2 секунди) на кадри (зазвичай 60 кадрів на секунду). Він перераховує значення для кожного кадру і перемальовує екран. Ваше завдання — не перевантажити його математикою (про це пізніше).
3. 🧪 Приклади (від простого до реального)
Приклад 1: "Серцебиття" (The Pulse)
Давайте зробимо коло, яке ритмічно збільшується.
Чого ви очікуєте? Коло має стати більшим, потім меншим, і так по колу.
/* 1. Сценарій */
@keyframes heartbeat {
0% {
transform: scale(1);
}
50% {
transform: scale(1.2); /* Збільшуємось на піку */
}
100% {
transform: scale(1); /* Повертаємось */
}
}
/* 2. Актор */
.heart {
width: 50px;
height: 50px;
background-color: red;
border-radius: 50%;
/* Запуск анімації */
animation-name: heartbeat;
animation-duration: 1s;
animation-iteration-count: infinite; /* Нескінченно */
}
Пояснення: Ми розбили час на три етапи. Початок (нормальний), середина (великий), кінець (нормальний). infinite змушує це повторюватись вічно.
Приклад 2: "Спіннер завантаження" (Loading...)
Класика жанру. Коли дані ще не прийшли, ми показуємо колесо, що крутиться.
Чого ви очікуєте? Елемент має обертатися навколо своєї осі на 360 градусів.
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.loader {
width: 40px;
height: 40px;
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db; /* Синій верх, щоб бачити обертання */
border-radius: 50%;
animation: spin 1s linear infinite;
}
Пояснення:
* Ми використали скорочений запис animation.
* Слово linear тут критично важливе. За замовчуванням анімації розганяються і гальмують (як потяг). Для спіннера це виглядає дивно, він має крутитися рівномірно. Тому linear.
Приклад 3: "Спливаюче повідомлення" (Toast Notification)
Уявіть, що користувач зберіг файл. Збоку виїжджає плашка "Збережено".
@keyframes slideIn {
0% {
transform: translateX(100%); /* Сховано за правим краєм */
opacity: 0;
}
100% {
transform: translateX(0); /* На своєму місці */
opacity: 1;
}
}
.toast {
background: #333;
color: white;
padding: 10px 20px;
/* Анімація */
animation: slideIn 0.5s ease-out forwards;
}
Пояснення:
* ease-out: Починається швидко, а в кінці плавно гальмує. Це виглядає природно, ніби повідомлення "припаркувалося".
* forwards: Дуже важливо! За замовчуванням після закінчення анімації елемент повертається до стану "до анімації" (зникне). forwards змушує його залишитись у стані 100%.
4. 🛠 Практична частина
Час забруднити руки кодом. Відкрийте ваш редактор (VS Code або CodePen).
Завдання 1: Світлофор
Створіть div-коло. Напишіть анімацію changeColor, яка змінює колір фону: Червоний (0%) -> Жовтий (50%) -> Зелений (100%). Тривалість 3 секунди.
Завдання 2: М’ячик (Bouncing Ball)
Зробіть коло, що "стрибає".
* 0%: transform: translateY(0)
* 50%: transform: translateY(-100px) (злетів угору)
* 100%: transform: translateY(0) (впав назад)
* Додайте animation-timing-function: ease-in-out для плавності.
Завдання 3: Виправ помилку Студент написав код, але квадрат не рухається. Чому?
.box {
width: 100px; height: 100px; background: blue;
animation-name: slideRight;
/* Чогось не вистачає... */
}
@keyframes slideRight {
to { transform: translateX(200px); }
}
(Підказка: Який параметр обов'язковий, щоб час пішов?)
Завдання 4: Міні-кейс "Приверни увагу"
У вас є кнопка "Купити". Зробіть так, щоб вона кожні 5 секунд легенько "трусилася" (wiggle effect), нагадуючи про себе, але не дратуючи.
* Підказка: Використовуйте rotate на маленькі кути (наприклад, -5deg, 5deg, -5deg, 0).
Завдання 5: А що, якщо...
Що буде, якщо встановити animation-delay: -1s (від’ємне значення) для анімації, яка триває 2 секунди? Спробуйте і поясніть результат.
5. 💡 Мислення як у розробника
Ось де ми переходимо від "я вмію кодити" до "я інженер".
1. Продуктивність (FPS) — це святе
Новачки часто анімують width, height, margin, top/left.
Це погано.
Чому? Тому що браузеру доводиться перераховувати геометрію всього сайту (Layout/Reflow) на кожному кадрі. Це вантажить процесор. Комп'ютер починає гудіти, як літак.
Як думає про:
"Я буду анімувати тільки transform (переміщення, масштаб, поворот) і opacity (прозорість)".
Ці дві властивості обробляються відеокартою (GPU). Це дешево і супер-плавно.
2. Не робіть морську хворобу
Те, що ви можете змусити все на сторінці літати, не означає, що ви повинні. Анімація — це як спеції. Трохи солі — смачно. Ложка солі — їсти неможливо. Анімація має: * Або спрямовувати увагу (подивіться сюди!). * Або пояснювати зміни (меню виїхало звідси).
3. Debugging
Якщо анімація працює не так, відкрийте Chrome DevTools -> вкладка Animations (натисніть Esc -> три крапки -> Animations). Ви зможете сповільнити час до 10% швидкості і побачити, що саме йде не так.
6. 🧩 Підсумок
Отже, що ми маємо сьогодні?
- Ви зрозуміли, що
@keyframes— це сценарій фільму, аanimation— це команда режисера. - Ви знаєте, що браузер сам заповнює проміжки між кадрами.
- Ви навчилися робити зациклені анімації (
infinite) та такі, що зберігають стан (forwards). - Ви (сподіваюсь) пообіцяли мені анімувати переважно
transformтаopacity.
Тепер ви можете створювати інтерфейси, які відчуваються живими, дихаючими та інтерактивними.
Що далі? Анімації в CSS класні, але вони "дурні" — вони просто виконуються. У наступних темах ми підключимо JavaScript, щоб запускати анімації саме тоді, коли користувач щось зробив (клікнув, проскролив, навів мишку). Це буде вже справжній інтерактив.
А поки — експериментуйте з @keyframes! Це і є CS50.