CSS-animatie is het meest praktische gereedschap om een statisch document om te toveren tot een levendige, vloeiende ervaring. Zonder ook maar één regel JavaScript te schrijven, kun je knoppen soepel van kleur laten veranderen, kaarten in beeld laten glijden en laadindicatoren laten draaien — uitsluitend met stijlregels. In deze gids behandel ik de twee kernmechanismen apart: transition, dat in werking treedt bij toestandsveranderingen, en @keyframes, voor getimede beweging in meerdere stappen.
transition: vloeiende overgangen tussen toestanden
transition vult automatisch de tussenstappen in wanneer de waarde van een eigenschap verandert. Wanneer een :hover, :focus of een via JavaScript toegevoegde class een kleur of grootte wijzigt, zie je dus een soepele overgang in plaats van een harde sprong. Het heeft vier kernonderdelen: welke eigenschap, over welke duur, met welke versnellingscurve en na welke vertraging.
.btn {
background: #4f46e5;
transform: scale(1);
transition: background 200ms ease, transform 200ms ease;
}
.btn:hover {
background: #6366f1;
transform: scale(1.05);
}
Hier neemt de transition-snelkoppeling, op volgorde, de eigenschap, de duur en de timingfunctie. Je kunt meerdere eigenschappen opsommen, gescheiden door komma's. Noem waar mogelijk de exacte eigenschappen in plaats van all te gebruiken; dat houdt de performance voorspelbaar en voorkomt dat eigenschappen die je niet bedoelde per ongeluk worden geanimeerd.
Timingfuncties (easing)
Of beweging natuurlijk aanvoelt, hangt grotendeels af van de snelheidscurve. In de echte wereld starten en stoppen objecten niet abrupt; ze versnellen en vertragen. CSS biedt hiervoor kant-en-klare trefwoorden en aangepaste curven:
ease— de standaard; een gebalanceerde curve die zacht begint en eindigt.linear— constante snelheid; ideaal voor draaiende laadindicatoren.ease-out— begint snel, eindigt langzaam; voelt natuurlijk voor elementen die in beeld komen.cubic-bezier(0.34, 1.56, 0.64, 1)— definieert je eigen curve; waarden boven 1 geven een licht "verend" effect.
Voor de meeste UI-micro-interacties voelen duren tussen 150 en 300 ms het natuurlijkst. Te kort en de verandering valt niet op; te lang en de interface voelt traag aan.
@keyframes: animaties in meerdere stappen
Een transition werkt alleen tussen twee toestanden: een begin en een einde. Voor beweging in meerdere fasen — een element dat eerst groeit en dan krimpt, of continu draait — gebruik je @keyframes. Eerst definieer je een reeks frames, daarna pas je die toe op een element met de eigenschap animation.
@keyframes pulse {
0% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.1); opacity: 0.7; }
100% { transform: scale(1); opacity: 1; }
}
.badge {
animation: pulse 1.5s ease-in-out infinite;
}
Percentages stellen punten op de tijdlijn van de animatie voor; from en to zijn snelkoppelingen voor 0% en 100%. De animation-snelkoppeling neemt, op volgorde, de naam, duur, easing, het aantal herhalingen (infinite voor eindeloos) en de richting.
Performance: wat moet je animeren?
Een vloeiende animatie streeft naar 60 frames per seconde. De sleutel om dat te halen is het animeren van eigenschappen die de browser niet dwingen de pagina-indeling opnieuw te berekenen. transform en opacity worden rechtstreeks op de GPU verwerkt zonder de lay-out te verstoren; daarom zouden ze je standaardkeuze moeten zijn.
- Goed:
transform(translate, scale, rotate) enopacity. - Vermijd:
width,height,top,left,margin— eigenschappen die bij elk frame een reflow veroorzaken.
Om een element naar links te schuiven, gebruik je bijvoorbeeld transform: translateX() in plaats van left. Wil je de browser laten weten dat een element bijna geanimeerd wordt, dan kun je will-change: transform; toevoegen — maar alleen wanneer je het echt nodig hebt, want overmatig gebruik verbruikt geheugen.
Toegankelijkheid: respect voor de voorkeur voor minder beweging
Sommige gebruikers hebben last van overmatige beweging of schakelen die op besturingssysteemniveau uit vanwege vestibulaire stoornissen. Die voorkeur eren met de media-query prefers-reduced-motion is een goede praktijk:
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
Deze regel schakelt decoratieve animaties effectief uit terwijl de interface volledig functioneel blijft.
Een praktisch voorbeeld: een kaart die omhoog in beeld verschijnt
Het onderstaande voorbeeld brengt een kaart in beeld door deze licht van onder naar boven en van transparant naar ondoorzichtig te verplaatsen. Omdat het alleen transform en opacity gebruikt, blijft het vloeiend.
@keyframes fade-up {
from { opacity: 0; transform: translateY(16px); }
to { opacity: 1; transform: translateY(0); }
}
.card {
animation: fade-up 400ms ease-out both;
}
De waarde both betekent dat de animatie zijn begintoestand behoudt voordat hij begint en zijn eindtoestand nadat hij is afgelopen, zodat de kaart op zijn plaats blijft zonder te flikkeren.
Veelgestelde vragen
Wat is het verschil tussen transition en animation?
transition werkt alleen tussen twee toestanden, meestal als reactie op een interactie (hover, focus, classwijziging). animation, gedefinieerd met @keyframes, beschrijft beweging in meerdere stappen die vanzelf kan starten en in een lus kan lopen.
Waarom haperen mijn animaties?
De gebruikelijke boosdoener is het animeren van eigenschappen als width, top of margin die bij elk frame een herberekening van de lay-out forceren. Overstappen op transform en opacity lost het meeste haperen op.
Kan ik een animatie bij het scrollen activeren zonder JavaScript?
Ja. In moderne browsers zijn scroll-gestuurde animaties mogelijk met CSS animation-timeline: view();. Voor bredere browserondersteuning blijft het toevoegen van een class via IntersectionObserver de meest betrouwbare aanpak.
Wil je je interface een verzorgd, vloeiend gevoel geven? Heb je hulp nodig bij performante CSS-animaties en micro-interacties, neem dan contact met me op.