Skip to content

Wszystko o WordPressie, tworzeniu stron — i nie tylko

🔄 Animacja obiektu przy przewijaniu: poradnik krok po kroku

🔄 Animacja obiektu przy przewijaniu: poradnik krok po kroku

Wchodzą Państwo na stronę, przewijają ją, a logo w rogu płynnie się obraca, reagując na każdy ruch kółka myszy. Wygląda to żywo, technologicznie i dodaje stronie tego „smaczku", który zostaje zauważony.

Stworzenie takiego obrotu jest prostsze, niż się wydaje. Nie potrzebują Państwo ciężkich bibliotek ani megabajtów frameworków do animacji. Wystarczy jeden div, kilka linijek CSS i dosłownie jeden blok JavaScript.

Poniżej analiza krok po kroku: od przygotowania obrazu po adaptację na ekrany mobilne. Kod jest sprawdzony, działający, bez zależności.

💡 Szybki przegląd:

  • Przygotowujemy obiekt SVG lub PNG i umieszczamy go w HTML
  • Ustalamy pozycję za pomocą position: fixed i konfigurujemy odstępy w jednostkach viewportu
  • Dodajemy procedurę obsługi scroll w JavaScript, która obraca obiekt przez transform: rotate()
  • Regulujemy prędkość obrotu, dzieląc window.scrollY przez współczynnik
  • Dla urządzeń mobilnych definiujemy media query z nową pozycją i czasem przejścia

1. Przygotowanie obiektu

Obiektem może być cokolwiek: ikona, logo, figura wektorowa, znak strzałki. Polecam SVG, nie traci ostrości podczas transformacji i waży grosze. Jeśli przezroczystość jest krytyczna, a nie ma Państwo wektora, sprawdzi się PNG.

Proszę umieścić obraz wewnątrz kontenera div i wstawić go do body, najlepiej na górze. Osobny div ułatwia zarządzanie: z czasem będą Państwo mogli dodać sąsiednie elementy lub wymienić obrazek, nie ruszając logiki pozycjonowania.

1<div id="scrollContainer">
2 <img src="img/scrollObject.svg" alt="scrollObject" id="scrollObject">
3</div>

Obiektów może być kilka, wystarczy nadać każdemu unikalny id i powielić logikę JS z przypisaniem do swojego elementu. Na początek zbudujmy jednak jeden działający egzemplarz.

2. Pozycjonowanie przez CSS

Gdzie umieścić obiekt? To zależy od celu:

  • Prawy dolny róg, miniaturowa ikona, która nie przeszkadza treści. Klasyka dla blogów i portfolio.
  • Lewy górny róg, wskaźnik pozycji przewijania (progress wheel).
  • Na środku dolnej krawędzi, duży element dekoracyjny, przyciągający uwagę do stopki.

Przeanalizujmy scenariusz z prawym dolnym rogiem, jest uniwersalny i nie zasłania nawigacji. W CSS proszę zdefiniować:

1#scrollObject {
2 position: fixed;
3 right: 3vw;
4 bottom: 3vh;
5 top: auto;
6 width: 7vh;
7 height: auto;
8 transition: 0.1s ease-out;
9}

Kluczowe jest position: fixed. To właśnie ono unieruchamia element względem okna przeglądarki, a nie dokumentu. Podczas przewijania treść się przesuwa, a obiekt pozostaje na swoim miejscu. Jednostki vw i vh (procenty szerokości i wysokości viewportu) automatycznie dopasowują odstępy do każdego ekranu, od smartfona po monitor 4K.

Właściwość transition: 0.1s ease-out wygładza szarpnięcia podczas zmiany pozycji. Dla obrotu jej rola jest drugorzędna, ale podczas zmiany rozmiaru okna lub media query przejście wygląda schludniej.

3. Animacja obrotu w JavaScript

CSS potrafi proste @keyframes, ale naszym zadaniem jest powiązanie kąta obrotu z pozycją przewijania. Tutaj wkracza JavaScript. Minimalny działający kod:

1const scrollObject = document.getElementById("scrollObject");
2
3window.addEventListener("scroll", () => {
4 scrollObject.style.transform = `rotate(${window.scrollY}deg)`;
5});

Co tu się dzieje: window.scrollY zwraca liczbę pikseli, o jaką strona została przewinięta w pionie. Ta liczba jest podstawiana do funkcji CSS rotate(), jeden piksel przewinięcia odpowiada jednemu stopniowi obrotu.

Jeśli obiekt obraca się zbyt szybko, proszę podzielić wartość przez współczynnik:

1const speedFactor = window.scrollY / 2;
2const scrollObject = document.getElementById("scrollObject");
3
4window.addEventListener("scroll", () => {
5 scrollObject.style.transform = `rotate(${speedFactor}deg)`;
6});

Proszę dobrać dzielnik do długości swojej strony. Wartość /2 spowalnia obrót o połowę, /4 czyni go płynnym i ledwo zauważalnym. Dla długich landing page'y proszę ustawić /6 lub /8, aby obiekt nie wykonał dziesięciu pełnych obrotów do połowy strony.

Uwaga o wydajności

Zdarzenie scroll jest wyzwalane dziesiątki razy na sekundę. Na prostej stronie z jednym transform jest to niezauważalne, ale jeśli mają Państwo kilka animowanych obiektów lub ciężki DOM, proszę opakować logikę w requestAnimationFrame:

1const scrollObject = document.getElementById("scrollObject");
2let ticking = false;
3
4window.addEventListener("scroll", () => {
5 if (!ticking) {
6 requestAnimationFrame(() => {
7 scrollObject.style.transform = `rotate(${window.scrollY}deg)`;
8 ticking = false;
9 });
10 ticking = true;
11 }
12});

requestAnimationFrame grupuje wywołania w ramki synchronizacji przeglądarki (zwykle 60 fps) i nie wymusza ponownego przeliczania stylów przy każdym zdarzeniu przewijania, co daje oszczędność CPU i baterii na urządzeniach mobilnych.

Proszę również dodać will-change: transform do reguły CSS #scrollObject. Zasugeruje to przeglądarce wcześniejsze wydzielenie warstwy kompozycji GPU i obrót będzie sprzętowo przyspieszony:

1#scrollObject {
2 /* ... остальные свойства ... */
3 will-change: transform;
4}

4. Adaptacja na urządzenia mobilne

Na ekranach mniejszych niż 600 pikseli prawy dolny róg może kolidować z menu typu burger lub przyciskiem „do góry". Rozsądnym rozwiązaniem jest przesunięcie obiektu na dół na środek, aby nie zasłaniał elementów interaktywnych:

1@media only screen and (max-width: 600px) {
2 #scrollObject {
3 transition: 0.2s ease-out;
4 margin-left: -4vh;
5 width: 8vh;
6 height: auto;
7 top: 10px;
8 left: 50%;
9 }
10}

Obiekt przesuwa się w górną część ekranu, jest centrowany przez left: 50% z ujemnym margin-left, klasyczny trik centrowania poziomego. Szerokość jest nieco zwiększona (8vh zamiast 7vh), aby skompensować mniejszą odległość oglądania.

Proszę zwrócić uwagę na transition: 0.2s ease-out w media query. Podczas przejścia z desktopu na mobilny (lub podczas zmiany rozmiaru okna) obiekt nie „przeskakuje" natychmiast, ale płynnie przesuwa się do nowej pozycji w ciągu 0.2 sekundy.

Ikona przewijania na ekranie smartfona

Jeśli pracują Państwo w Vue lub React, proszę wydzielić obiekt przewijania do osobnego komponentu. Dzięki temu można go zawiesić w głównym App.vue lub w layout, aby animacja była obecna na wszystkich stronach jednocześnie, bez duplikowania kodu.

Rezultat animacji obiektu przewijanego po adaptacji

Nowoczesna alternatywa: animacje CSS sterowane przewijaniem

W latach 2024-2025 przeglądarki oparte na Chromium (Chrome, Edge, Opera) uzyskały natywną obsługę animation-timeline: scroll(), czyli animacji powiązanych z przewijaniem bez ani jednej linijki JavaScript. Wygląda to tak:

1@keyframes rotate {
2 to { transform: rotate(360deg); }
3}
4
5#scrollObject {
6 animation: rotate linear;
7 animation-timeline: scroll();
8}

Plus: zero JavaScriptu, minus: na razie tylko w Chromium (Firefox i Safari są w trakcie wdrażania). Dla progressive enhancement można to połączyć: dać wersję CSS nowoczesnym przeglądarkom, a procedurę obsługi JS pozostawić jako fallback dla reszty. Szczegóły na MDN.

⁉️🤔 Często zadawane pytania

Czy można animować nie tylko obrót, ale też skalę lub przezroczystość?

Tak. transform obsługuje kilka funkcji jednocześnie. Aby obiekt obracał się i zmniejszał podczas przewijania: scrollObject.style.transform = \rotate(${window.scrollY}deg) scale(${1 - window.scrollY / 5000});. Przezroczystość przez opacity oddzielnie od transform. Można łączyć do pięciu-sześciu parametrów, ale proszę testować: wielokrotne transformacje na słabych urządzeniach mogą powodować micro-stutter. Jeden-dwa parametry plus will-change: transform to bezpieczny pułap dla 60 fps.

Co jest lepsze: SVG czy PNG do animacji?

SVG, zdecydowanie. Skaluje się bez utraty ostrości przy każdym obrocie i rozdzielczości ekranu, waży mniej, a przeglądarka renderuje go jako wektor (nie ma pikselowych schodków na krawędziach po rotate). Proszę sięgać po PNG tylko wtedy, gdy mają już Państwo gotową grafikę rastrową i nie ma czasu na przeróbki. Proszę unikać JPEG dla obracanych obiektów: po obrocie artefakty kompresji stają się bardziej widoczne.

Jak sprawić, by animacja uruchamiała się tylko wtedy, gdy obiekt jest w obszarze widocznym?

Proszę użyć IntersectionObserver. Zamiast podpinania się pod globalny scroll, śledzą Państwo, czy obiekt znalazł się w viewporcie, i dopiero wtedy włączają obrót. Oszczędza to zasoby, gdy element jest poza ekranem. Podstawowy szablon: proszę utworzyć observer z threshold: 0, w callbacku dodawać/usuwać klasę .active, a procedurę obsługi przewijania JS uzależnić od obecności tej klasy.

Dlaczego na mojej stronie animacja się zacina?

Trzy typowe przyczyny. Pierwsza: brak will-change: transform, przeglądarka nie przekazuje elementu do kompozycji GPU i przelicza layout przy każdej klatce. Druga: do elementu zastosowano właściwości wywołujące reflow (takie jak width, height, margin lub padding) wewnątrz tej samej procedury obsługi przewijania. Proszę zastąpić je przez transform: scale() i transform: translate(). Trzecia: callback przewijania wykonuje się bez requestAnimationFrame i generuje zbędne przerysowania między klatkami. Proszę opakować logikę we wzorzec rAF (przykład w sekcji „Uwaga o wydajności").

Czy konieczne jest używanie JavaScriptu? Są przecież rozwiązania czysto CSS-owe.

CSS-owe @keyframes są powiązane z czasem, a nie z pozycją przewijania. Owszem, animation-timeline: scroll() zmienia zasady gry, ale wsparcie przeglądarek jest wciąż niepełne (patrz sekcja 4). Na połowę 2026 roku rozwiązanie JavaScript z scrollY + transform jest wciąż najbardziej niezawodnym, wieloprzeglądarkowym sposobem na powiązanie obrotu z przewijaniem. Cały kod mieści się w 5 linijkach, nie ciągnie zależności i działa od Internet Explorera 10 po najnowszego Chrome'a.

Czy warto dodać animację przewijania na swoją stronę?

Obracanie obiektu podczas przewijania to nie tylko „fajna sztuczka". To mikrointerakcja, która daje odwiedzającemu dotykową informację zwrotną: „przesuwam stronę i coś się dzieje". Odpowiednio skonfigurowana nie irytuje i nie rozprasza, a dodaje stronie indywidualności.

Jeśli strona jest minimalistyczna, proszę ograniczyć się do jednego małego obiektu w rogu i współczynnika /4 lub /6. Dla landing page'y i portfolio można grać odważniej: duży centralny element z /2, łączona animacja obrotu i skali, zmiana obrazka po osiągnięciu określonego scrollY.

Główna zasada: animacja przewijania ma uzupełniać treść, a nie konkurować z nią o uwagę. Jeden obiekt, płynny ruch, zero natarczywości, a Państwa strona zostanie zapamiętana.