Lekcja 26

Animacje CSS: @keyframes

@keyframes pozwala opisać sekwencję zmian CSS w czasie. W tej lekcji zbudujesz podstawowy model animacji: klatki, czas trwania, krzywą ruchu, liczbę powtórzeń, kierunek i stan przed oraz po animacji.

Cele lekcji

Po ukończeniu tej lekcji będziesz umieć:

  • zdefiniować animację przez @keyframes,
  • podpiąć animację przez animation-name i animation-duration,
  • kontrolować tempo przez animation-timing-function,
  • używać animation-delay, animation-iteration-count i animation-direction,
  • zrozumieć rolę animation-fill-mode,
  • zapisać animację skrótem animation bez utraty czytelności.

Kontekst praktyczny

Animacje CSS pojawiają się w loaderach, pustych stanach, komunikatach sukcesu, skeletonach, wskaźnikach postępu, mikrointerakcjach i elementach, które mają przyciągnąć uwagę użytkownika. Ich zadaniem jest komunikacja zmiany, nie dekorowanie każdej powierzchni.

W praktyce: transition opisuje przejście między dwoma stanami, a @keyframes pozwala zaplanować wiele kroków animacji. Jeżeli wystarcza hover do hover, użyj transition. Jeżeli potrzebujesz sekwencji, użyj @keyframes.

Czym są @keyframes

@keyframes definiuje, jak wartości CSS zmieniają się w czasie. Możesz użyć prostych punktów from i to albo procentów, gdy animacja ma więcej etapów.

@keyframes fade-in {
  from {
    opacity: 0;
    transform: translateY(.5rem);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

Sama definicja @keyframes niczego jeszcze nie uruchamia. Trzeba przypisać ją do elementu przez właściwości animation-*.

Name i duration

animation-name wskazuje nazwę animacji, a animation-duration ustala czas trwania jednego przebiegu. Bez czasu trwania animacja domyślnie ma 0s, więc użytkownik jej nie zobaczy.

.toast {
  animation-name: fade-in;
  animation-duration: 240ms;
}

Dla UI krótkie animacje wejścia zwykle mieszczą się w przedziale 180ms - 320ms. Dłuższe ruchy warto zostawić dla elementów informacyjnych, które nie blokują pracy użytkownika.

Timing i delay

animation-timing-function określa rytm zmiany, a animation-delay opóźnia start. Tak jak w transition, krzywa ruchu wpływa na to, czy animacja wydaje się lekka, techniczna czy ospała.

.panel {
  animation-name: fade-in;
  animation-duration: 260ms;
  animation-timing-function: ease-out;
  animation-delay: 80ms;
}

Delay stosuj ostrożnie. Opóźniony feedback po kliknięciu może sprawiać wrażenie, że interfejs nie zareagował.

Iteration i direction

animation-iteration-count mówi, ile razy animacja ma się powtórzyć. animation-direction kontroluje kierunek przebiegu: normalny, odwrócony albo naprzemienny.

.status-dot {
  animation-name: pulse;
  animation-duration: 1.2s;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}

Animacje nieskończone są kosztowne poznawczo. Używaj ich tylko wtedy, gdy użytkownik naprawdę potrzebuje sygnału ciągłego procesu, na przykład ładowania albo aktywnego statusu.

Fill mode

animation-fill-mode określa, czy element ma zachować style z początku albo końca animacji. Najczęściej spotkasz forwards, gdy po animacji element powinien zostać w stanie końcowym.

.success-message {
  animation-name: fade-in;
  animation-duration: 240ms;
  animation-fill-mode: both;
}

both łączy zachowanie backwards i forwards. Jest przydatne, gdy animacja ma opóźnienie, ale element powinien wyglądać poprawnie już przed startem.

Skrót animation

Skrót animation pozwala zapisać nazwę, czas, timing, delay, liczbę powtórzeń, kierunek i fill-mode w jednej deklaracji. To wygodne, ale przy nauce warto rozumieć każdy składnik osobno.

.loader {
  animation: pulse 1.2s ease-in-out 0s infinite alternate both;
}

Jeżeli skrót robi się trudny do czytania, wróć do osobnych właściwości. Kod edukacyjny i produkcyjny powinien być łatwy do utrzymania.

Demo animacji

Poniższe demo pokazuje cztery typowe zastosowania @keyframes: wejście komunikatu, puls statusu, ruch wskaźnika i pasek postępu.

@keyframes

Sekwencje ruchu w UI

fade-in Komunikat wejścia

Krótka animacja pokazuje nową treść bez gwałtownego przeskoku.

pulse Status aktywny

Puls powinien być delikatny i używany tylko dla realnego procesu.

Progress

Pasek postępu

  • nameprogress-fill
  • duration2.8s
  • timingease-in-out
  • fill-modeforwards

Ta animacja ma stan końcowy, więc używa forwards, zamiast wracać do pustego paska.

Najczęstsze błędy początkujących

  • Definiowanie @keyframes bez przypisania animacji do elementu.
  • Brak animation-duration, przez co animacja trwa 0s.
  • Nadużywanie infinite dla dekoracyjnych elementów.
  • Animowanie właściwości, które powodują kosztowne przeliczanie layoutu.
  • Używanie animacji do sygnałów, które powinny być zwykłym stanem UI.
  • Zapominanie o tym, że następna lekcja będzie wymagała kontroli ruchu i preferencji użytkownika.

Mini zadanie

Zbuduj prosty komunikat sukcesu z animacją wejścia.

  • Zdefiniuj @keyframes success-enter z opacity i transform.
  • Dodaj animation-name, animation-duration i animation-timing-function.
  • Ustaw animation-fill-mode: both.
  • Dodaj mały status dot z animacją pulse powtarzaną maksymalnie trzy razy.
  • Sprawdź, czy animacja nie przesuwa innych elementów w układzie.

Checklista

  • Potrafię zdefiniować @keyframes przez from/to albo procenty.
  • Wiem, że animacja wymaga nazwy i czasu trwania.
  • Rozumiem różnicę między transition i @keyframes.
  • Potrafię kontrolować timing, delay, liczbę powtórzeń i kierunek.
  • Wiem, kiedy użyć animation-fill-mode.
  • Unikam nieskończonych animacji bez realnego celu.

Podsumowanie lekcji

@keyframes pozwala opisać sekwencję zmian w czasie i uruchomić ją przez właściwości animation-*. Dobra animacja ma konkretny cel, rozsądny czas trwania, przewidywalny kierunek i nie próbuje naprawiać problemów layoutu.

Kolejny krok roadmapy to dostępne animacje i prefers-reduced-motion.

Przejdź do Lekcji 27