Lekcja 12. Trzy drogi animacji

wrz 3, 2026 | Kurs SVG

SMIL, CSS, JavaScript — i jak wybrać, nie żałując potem

SVG można animować na trzy niezależne sposoby. Nie są to warianty tego samego mechanizmu ani kolejne wersje tej samej technologii — to trzy osobne systemy, o różnych mocnych stronach i różnych ograniczeniach.

Nie ma wśród nich jednego słusznego. Jest za to dość prosta reguła wyboru i do niej dojdziemy na końcu.

Droga pierwsza: SMIL

Animacja zapisana wewnątrz samego pliku SVG, w postaci znaczników.

html

<circle cx="40" cy="40" r="16" fill="#e05c1a">
  <animate attributeName="cx"
           values="40; 200; 40"
           dur="2.5s"
           repeatCount="indefinite"/>
</circle>

Element <animate> siedzi w środku kształtu, który animuje. Mówi, który atrybut zmieniać, jakie wartości po kolei przyjmować i jak długo ma to trwać.

Do przekształceń służy osobny znacznik <animateTransform>, bo transform nie jest zwykłym atrybutem tekstowym — trzeba podać jeszcze type, czyli o jaki rodzaj przekształcenia chodzi.

Obie animacje działają w podglądzie na żywo, bez ani jednej linijki CSS i bez skryptu. Ustaw obie długości na tę samą wartość, a ruchy się zsynchronizują.

Największa zaleta SMIL: plik jest samowystarczalny. Animacja działa nawet wtedy, gdy SVG jest wstawiony przez <img src="ikona.svg">, ustawiony jako background-image albo otwarty bezpośrednio jako plik. Żadna inna metoda tego nie potrafi — o czym za chwilę.

Trzeba jednak wspomnieć o pewnym epizodzie, bo do dziś krąży w internecie i budzi niepotrzebny lęk. Dziesięć lat temu Chrome ogłosił zamiar wycofania SMIL, a potem wycofał się z tego zamiaru. Wsparcie zostało i dziś działa we wszystkich aktualnych przeglądarkach. Nadal jednak trafisz na artykuły i odpowiedzi na forach napisane w tamtym okresie, które odradzają SMIL jako „przestarzały". Warto wiedzieć, skąd to się bierze.

Droga druga: CSS

Ta sama robota, ale w składni, którą znasz z reszty frontendu.

html

<style>
  .puls-demo {
    animation: puls-demo 2s ease-in-out infinite;
    transform-origin: 120px 65px;
  }
  @keyframes puls-demo {
    0%, 100% { transform: scale(1);   opacity: 1;  }
    50%      { transform: scale(1.4); opacity: .4; }
  }
</style>

Znacznik <style> może siedzieć wewnątrz SVG, dokładnie tak jak tutaj. Zwykle jednak wygodniej trzymać te reguły w arkuszu strony.

Zalety są oczywiste: znane funkcje czasowe, :hover, zapytania medialne, transition do prostych przejść i możliwość sterowania wszystkim przez zmianę klasy.

Ograniczenia są mniej oczywiste, ale ważne. CSS działa tylko wtedy, gdy SVG jest wstawiony inline — jako <svg> w kodzie strony albo z regułami wewnątrz pliku. Grafika osadzona przez <img> jest dla arkusza stylów strony czarną skrzynką i żadna reguła do niej nie dotrze. Wrócimy do tego w osobnej lekcji, bo to jedno z najczęstszych źródeł frustracji.

Druga rzecz: nie każdy atrybut SVG jest właściwością CSS. cxcyropacity i fill animować można. Atrybut d ścieżki — w części przeglądarek tak, w części nie. Atrybutów w rodzaju points czy viewBox nie ruszysz w ogóle. SMIL nie ma tego ograniczenia, bo działa na atrybutach, a nie na właściwościach.

I jeszcze jedna pułapka, którą widać w widgecie powyżej: reguły ze znacznika <style> w osadzonym SVG obowiązują na całej stronie, a nie tylko wewnątrz tej grafiki. Klasa nazwana .ikona nadpisze wszystkie inne .ikona w dokumencie. Dlatego klasy w tym presecie mają celowo dziwaczne nazwy.

Droga trzecia: JavaScript

Skrypt zmieniający atrybuty w czasie — samodzielnie albo przez bibliotekę.

js

element.setAttribute("cx", nowaWartosc);

To jedyna droga, gdy animacja ma reagować zamiast po prostu grać: podążać za kursorem, zależeć od pozycji przewijania, od danych z API, od fizyki albo od decyzji użytkownika. Bibliotek jest sporo, w praktyce spotkasz głównie GSAP i anime.js.

Warto znać też Element.animate() — Web Animations API, wbudowane w przeglądarki. Daje kontrolę czasu podobną do biblioteki, bez dokładania kilkudziesięciu kilobajtów.

Do prostych rzeczy JavaScript jest jednak przerostem formy. Pulsujące koło nie potrzebuje skryptu, a każdy skrypt to coś, co może się nie wykonać.

Zwróć uwagę, że w playgroundzie tej lekcji nie da się przetestować tej trzeciej drogi — podgląd usuwa znacznik <script> przed wyświetleniem. To ta sama zasada, o której będzie lekcja o bezpieczeństwie: SVG jest kodem, więc kod z niego usuwamy.

Jak wybrać

Reguła, która sprawdza się w większości przypadków:

  • Animacja ma żyć w pliku i działać wszędzie, także w <img> i w tle → SMIL.
  • Animacja jest częścią interfejsu, ma reagować na :hover albo być sterowana klasą → CSS.
  • Animacja ma zależeć od danych, przewijania, kursora albo mieć sterowaną oś czasu → JavaScript.

W praktyce metody się mieszają i nie ma w tym nic złego. Logo z animacją SMIL może stać na stronie, w której cała reszta ruchu jest w CSS.

Rzecz, o której nie wolno zapomnieć

Część osób ma zawroty głowy, mdłości albo napady migreny od ruchu na ekranie. System operacyjny pozwala im to zgłosić, a przeglądarka przekazuje tę informację dalej:

css

@media (prefers-reduced-motion: reduce) {
  .puls-demo { animation: none; }
}

To nie jest ozdobnik dla purystów dostępności. Dla części odbiorców to różnica między korzystaniem ze strony a zamknięciem jej. Trzy linijki i temat załatwiony — a przy SMIL trzeba to obsłużyć skryptem, bo znaczniki animacji nie widzą zapytań medialnych.

Druga zasada z tej samej rodziny: nie animuj bez końca tego, co nie niesie informacji. Wskaźnik ładowania ma prawo się kręcić, bo mówi „pracuję". Logo kręcące się w kółko przez cały czas wizyty tylko męczy.

Podsumowanie

  • SMIL to animacja w znacznikach, wewnątrz pliku; jako jedyna działa w <img> i w tle.
  • Straszenie wycofaniem SMIL pochodzi sprzed dekady i jest nieaktualne.
  • CSS daje znaną składnię, :hover i zapytania medialne, ale wymaga SVG wstawionego inline.
  • Nie każdy atrybut SVG da się animować w CSS; SMIL nie ma tego ograniczenia.
  • Reguły <style> wewnątrz osadzonego SVG działają na całą stronę.
  • JavaScript jest potrzebny wtedy, gdy animacja ma na coś reagować.
  • prefers-reduced-motion to nie ozdobnik — dla części odbiorców to warunek korzystania ze strony.

W następnej lekcji wracamy do stroke-dasharray z lekcji siódmej i składamy z niego najpopularniejszy efekt w całym SVG: linię, która rysuje się sama.


Do wypróbowania: w presecie SMIL dopisz do koła drugą animację, na przykład na promieniu: <animate attributeName="r" values="16; 6; 16" dur="1s" repeatCount="indefinite"/>. Dwie animacje na jednym kształcie działają równolegle i niezależnie — w CSS wymagałoby to jednej wspólnej klatkowej sekwencji.