Animații Scroll-Driven în CSS Pur (fără JS)
Ani la rând, animarea elementelor la derularea paginii a impus adăugarea de sute de kiloocteți de biblioteci greoaie JavaScript (GSAP ScrollTrigger, Locomotive Scroll) sau ascultători costisitori pe evenimentul window.onscroll care blocau firul principal de execuție. Noua specificație W3C Scroll-driven Animations mută controlul direct în CSS, rulând fluid pe placa video la 60–120 FPS.
@keyframes să fie legată de trecerea timpului în secunde (animation-duration: 2s), proprietatea animation-timeline leagă progresul animației de la 0% la 100% direct de procentajul de derulare al paginii sau al unui container!
1. De ce este o revoluție pentru performanța web?
Când folosești JavaScript pentru a urmări poziția de derulare (scroll listener), browserul este forțat să ruleze cod JS pe Main Thread (firul principal). Dacă procesorul este ocupat cu analiza DOM-ului sau cu alte sarcini, animațiile devin sacadate (efectul de jank).
Cu animation-timeline nativ în CSS, motorul browserului procesează derularea și compunerea cadrelor pe Compositor Thread (direct pe GPU). Astfel, chiar dacă firul principal JavaScript este temporar ocupat de un script greu, derularea și animația rămân perfect netede la 120 Hz pe ecrane de ultimă generație!
2. Scenariul 1: Bară de Progres a Lecturii în 3 Linii de Cod
Bara subțire de la partea superioară a articolelor tehnice care indică cât la sută din pagină a fost parcurs poate fi implementată fără nicio linie de JavaScript:
/* 1. Definim animația simplă de scalare pe orizontală */
@keyframes readingProgress {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
/* 2. Aplicăm animația pe bara fixă */
.reading-progress-bar {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 4px;
background: var(--accent);
transform-origin: 0% 50%;
z-index: 9999;
/* Legăm animația de derularea întregii pagini */
animation: readingProgress linear;
animation-timeline: scroll();
}
Funcția scroll() monitorizează implicit cel mai apropiat strămoș cu bară de derulare (în mod obișnuit întregul document <html>).
3. Scenariul 2: Apariție Fluidă la Intrarea în Ecran cu view()
În timp ce scroll() măsoară întregul document, funcția view() este concepută special pentru a urmări intrarea și ieșirea unui element specific din fereastra vizuală (viewport) (echivalentul nativ al API-ului JavaScript IntersectionObserver):
/* Animație de Fade-In cu ridicare ușoară */
@keyframes revealCard {
from {
opacity: 0;
transform: translateY(40px) scale(0.95);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
.reveal-on-scroll {
animation: revealCard linear both;
animation-timeline: view();
animation-range: entry 10% cover 30%;
}
Înțelegerea Intervalelor de Vizualizare (animation-range)
Proprietatea animation-range controlează cu precizie milimetrică momentul când începe și când se finalizează animația:
| Cuvânt Cheie | Descriere Comportament Vizual |
|---|---|
entry |
De la momentul în care marginea de sus a elementului atinge marginea de jos a ecranului până când elementul a intrat complet. |
cover |
Pe toată durata în care elementul este vizibil (de la primul pixel care intră până la ultimul care iese). |
contain |
Doar pe durata în care elementul este complet inclus în viewport. |
exit |
De la momentul în care elementul începe să părăsească partea superioară a ecranului. |
4. Tehnica de Îmbunătățire Progresivă (@supports)
Deoarece specificația este adoptată în prezent pe scară largă în motoarele Chromium (Chrome 115+, Edge) și în curs de implementare în Firefox și Safari (sub flag tehnic în versiunile curente), este esențial să folosim directiva @supports pentru a garanta că elementele rămân vizibile pe browserele care nu au activată specificația:
/* Elementul este vizibil în mod implicit pe toate browserele */
.card-articol {
opacity: 1;
transform: none;
}
/* Dacă browserul suportă animation-timeline, aplicăm efectul pe GPU */
@supports (animation-timeline: view()) {
.card-articol {
animation: revealCard linear both;
animation-timeline: view();
animation-range: entry 15% cover 35%;
}
}
5. Bune Practici & Respectarea Preferințelor Utilizatorului
- Respectă prefers-reduced-motion: Unii utilizatori suferă de tulburări vestibulare cauzate de mișcări continue la derulare. Dezactivează întotdeauna animațiile de scroll când utilizatorul a solicitat mișcare redusă în sistemul de operare:
@media (prefers-reduced-motion: reduce) { .reveal-on-scroll, .reading-progress-bar { animation: none !important; } } - Animează doar transform și opacity: Nu încerca să animezi dimensiuni (
height,width) sau poziții (top) pe scroll, altfel forțezi browserul să recalculeze arborele geometric de layout la fiecare pixel derulat.