Ik bouw sites in de Antigravity-stack: HTML, CSS en JavaScript — met GSAP voor animaties die meer vragen dan CSS alleen kan geven. Maar dat betekent niet dat ik alles met GSAP doe. De juiste tool voor de juiste situatie maakt code sneller, leesbaarder en makkelijker te onderhouden.
Dit is mijn beslisschema na honderden uren animatiewerk.
Wanneer CSS voldoende is
CSS transitions en keyframes zijn de juiste keuze als:
- Het gaat om hover- en focus-states. Button color verandert bij hover, een card lift iets op, een link krijgt een underline-animatie — dit is precies waarvoor CSS transitions bedoeld zijn. Minder dan tien regels, geen JavaScript nodig.
- De animatie loopt in een lus. Een loading-spinner, een infinite-scroll ticker, een pulserende indicator — CSS keyframes met
animation-iteration-count: infinitedoen dit efficiënter dan GSAP, want de browser optimaliseert herhalende CSS-animaties beter. - Je alleen opacity en transform animeert. De browser kan opacity en transform animeren op de GPU — dat is vrijwel altijd smooth. Als je alleen die twee eigenschappen nodig hebt, is CSS de juiste keuze.
- De timing simpel is. Één element, één delay, één easing-curve — CSS doet dat prima.
Wanneer je GSAP nodig hebt
GSAP wordt de betere keuze zodra:
Je meerdere elementen sequentieel wil animeren. GSAP's gsap.timeline() laat je een reeks animaties aan elkaar knopen met exacte timing en stagger-opties. Hetzelfde doen in CSS vereist een hoop handmatige delay-berekeningen die fragiel zijn zodra je iets verandert.
Animaties scroll-gedreven zijn. ScrollTrigger is de sterkste reden om GSAP te gebruiken. De plugin laat je elementen animeren op basis van scrollpositie — met scrubbing, pinning en nauwkeurige start/end-triggers. CSS heeft hier geen equivalent.
Je animaties wil pauzeren, omkeren of programmatisch besturen. GSAP-animaties zijn JavaScript-objecten met een volledige API: .pause(), .reverse(), .seek(), .kill(). Je kunt ze reageren op gebruikersinteracties op manieren die CSS niet toestaat.
Je cross-browser betrouwbaarheid nodig hebt voor complexe keyframes. CSS-animaties gedragen zich soms anders tussen browsers bij complexe timing-functies of wanneer je custom properties gebruikt als animatiewaarden. GSAP normaliseert dit — het werkt overal hetzelfde.
Een veelgemaakte fout
CSS custom properties (CSS variabelen) kun je niet gebruiken als timing-functie in een animation shorthand:
/* Dit werkt NIET: */
:root { --ease: cubic-bezier(.16,1,.3,1); }
animation: fadeIn .6s var(--ease) forwards; /* browser negeert de timing */
/* Dit werkt wel: */
animation: fadeIn .6s cubic-bezier(.16,1,.3,1) forwards;
De browser kan custom properties in animation shorthands niet betrouwbaar parsen als timing-functie op het moment dat de animatie wordt gerenderd. Het element blijft dan op opacity: 0 staan en je ziet niets. In GSAP heb je dit probleem niet — je geeft de easing direct mee als string of object.
Mijn vuistregel
- Hover/focus states → CSS
- Loopende decoratieve animaties → CSS keyframes
- Entrance-animaties bij laden → GSAP (controle over timing en stagger)
- Scroll-gedreven animaties → GSAP + ScrollTrigger, altijd
- Complexe sequenties met meerdere elementen → GSAP timeline
- Alles wat je programmatisch wil besturen → GSAP
Prestatieoverwegingen
GSAP voegt ~70kb toe aan je pagina (gezipt: ~27kb). Voor de meeste sites is dat verwaarloosbaar — zeker als je het laadt via CDN met HTTP/2. Laad het altijd via een CDN (jsDelivr of Cloudflare) zodat browsers het kunnen cachen over meerdere sites.
Ongeacht of je CSS of GSAP gebruikt: animeer alleen opacity en transform. Animaties op width, height, padding of top/left triggeren browser reflow — dat is duur en veroorzaakt jank. Gebruik scaleX(), scaleY() en translateY() in plaats van layout-properties.
Vragen over animaties in jouw project? Stuur me een bericht — ik kijk graag mee.