16 września 2025

4 min

Optymalizacja wydajności renderowania animacji na stronie

Niektóre techniki animowania mogą obciążać system bardziej niż inne. Właściwości CSS, takie jak margins, paddings, positions (np. top, left) wpływają na rozmiar i położenie elementów, co powoduje, że przeglądarka musi ponownie obliczać układ strony i rysować elementy w każdej klatce animacji. Z kolei inne właściwości, jak opacity, transform czy z-index, nie wymagają przeliczania układu ani odmalowywania, co sprawia, że ich animacja wykorzystuje mniej zasobów.

Zobaczcie to na danym przykładzie:

Zanim przeglądarka wyświetli ostateczną stronę, w procesie renderowania występuje kilka kroków. Na powyższym przykładzie możemy zobaczyć że: - width, height, padding… powodują przeliczenie wszystkich kroków - color, border-style, visibility… nie powodują przeliczenia układu - z-index, transform, opacity… nie powodują przeliczenia ani układu ani malowania

Zlokalizowanie problemu

Pierwszym krokiem było użycie opcji podświetlania “Paint” w narzędziach deweloperskich Chrome.

Po zbadaniu podejrzanych animacji odkryliśmy coś ciekawego. Naszym oczekiwaniem było to że animacja będzie wpływać tylko na określony obszar, a z jakiegoś powodu powodowała niepotrzebny “repaint” innych elementów. Zajęło to nam dosłownie kilka minut, aby znaleźć na naszej stronie inne elementy wykazujące podobne zachowanie, np: Nagłówek strony został zaprojektowany w dwóch wersjach: pełnej i minimalistycznej. Pełna wersja wyświetla się podczas pierwszego wejścia na stronę oraz przy przewijaniu strony do góry. W pozostałych sytuacjach, gdy użytkownik przegląda treści lub przewija stronę w dół, wyświetlana jest wersja minimalistyczna. Animacja przejścia między tymi wersjami ma efekt wysuwania dodatkowych elementów nagłówka od góry, co nadaje płynności i dynamiki podczas przeglądania strony.

Ta animacja pierwotnie została zaimplementowana w następujący sposób:

Co jest źle?

Tak zaimplementowana animacja nie jest optymalna i ma kilka istotnych wad. Przeglądarka wykonuje niepotrzebną pracę, odświeżając zawartość, której nie powinna. Po pierwsze zmiana odstępu wpływa na układ całego komponentu. Po przeliczeniu układu, przeglądarka musi odświeżyć te części strony (repaint), które zostały dotknięte zmianą marginesu, jeśli zmiana marginesu wpływa na wiele elementów. Po drugie użycie transition: all jest mało wydajne, ponieważ powoduje animację wszystkich możliwych właściwości CSS elementu, nawet tych, które nie są potrzebne. Poniżej możemy zobaczyć ile było przeliczeń stylów na sekundę oraz jakie elementy były przeliczane/odświeżane przy użyciu pierwotnego sposobu. Średnio mieliśmy 80 odświeżeń na sekundę.

Poznaj nasze podejście konsultingowe.

Czytaj więcej o Consultingu Izometryczny rysunek techniczny trójwymiarowego sześcianu z widocznymi krawędziami i wewnętrzną strukturą siatki

Optymalizacja animacji nagłówka

Naszym celem było maksymalne uniknięcie kroków związanych z przeliczaniem układu i odświeżaniem elementów. Więcej na temat optymalizacji renderowania strony można przeczytać tutaj.

Zaczęliśmy optymalizować to krok po kroku. Ograniczyliśmy właściwości transition do animowania tylko właściwości transform, zamiast używania ogólnego zapisu all. Zamiast animować margines, użyliśmy właściwości transform (translate3d). Transformacje są zazwyczaj obsługiwane przez GPU, co poprawia wydajność malowania i ponownego malowania. Używając właściwości transform, pozwalamy przeglądarce pominąć kroki związane z przeliczaniem układu i odświeżaniem. Przeglądarka po prostu przesuwa już namalowane warstwy, co nazywa się kompozycją. Przepisana wersja:

Zrzut ekranu DevTools z analizą wydajności: flame chart z wywołaniami funkcji, podświetlone Recalculate Style (1,28 ms, 59 elementów).

Promowanie elementów

Animowany element musi być na własnej warstwie kompozycji. Żeby to osiągnąć, można użyć właściwości will-change, która będzie promowała nasz element.  will-change: transform;  Informujemy dzięki temu przeglądarkę,  że przewidujemy zmianę właściwości transform komponentu, tym samym zwiększamy prawdopodobieństwo, że element zostanie przeniesiony do osobnej warstwy kompozycji. Ostrzeżenie: Nie promuj elementów bez potrzeby.

Unikaj nadmiernego stosowania tej reguły. Warstwy wymagają pamięci i zarządzania.

Więcej na temat właściwości will-change oraz zarządzania liczbą warstw można przeczytać tutaj oraz  tutaj



Wyniki

Po zastosowaniu nowego podejścia, średnia liczba przeliczeń układów i stylów na sekundę odświeżeń strony zmniejszyła się do 2-4 razy na sekundę. Ponadto, reflow i repaint są teraz wykonywane tylko w tych miejscach, gdzie są absolutnie konieczne.

Warto zauważyć, że nagłówek dalej zawiera komponenty, które wywołują reflow i repaint. W naszym przypadku kilka ikonek miało ustawioną właściwość opacity, przez co zmiana transition w nadrzędnym komponencie wymuszała repaint tych ikonek.

Porozmawiajmy o obszarach potencjalnej współpracy!

Więcej artykułów na ten temat znajdziesz na naszym blogu