🎬 Transitions & animaties
Home / CSS-track / Les 10

🎬 Transitions & animaties

Les 10 van 12 · ~25 min · CSS-track

Stap 1 van 7

Beweging maakt een interface levend. Met transitions animeer je hover-effecten soepel. Met transform beweeg, schaal en roteer je elementen. Met @keyframes maak je herhalende animaties — allemaal zonder JavaScript.

transition — soepele overgangen

transition maakt dat een CSS-waardeverandering vloeiend verloopt in plaats van abrupt te springen.

/* property  duur     timing-function  vertraging */
transition: background-color 0.3s ease;
transition: all 0.25s ease;          /* animeer alle properties ⭐ */
transition: transform 0.3s ease, opacity 0.2s ease; /* meerdere */

/* Timing functions */
ease          /* langzaam start, piek, langzaam einde (standaard) */
ease-in       /* langzaam starten, snel eindigen */
ease-out      /* snel starten, langzaam eindigen */
ease-in-out   /* langzaam starten en eindigen */
linear        /* constante snelheid */
cubic-bezier(0.68, -0.55, 0.27, 1.55) /* custom (bijv. bounce) */

Live demo — hover over de knop en kaart

Hover mij
/* Zo is de knop hierboven gemaakt */
.knop {
  background: #2dd4bf;
  transition: all 0.25s ease;
}
.knop:hover {
  background: #0d9488;
  transform: translateY(-2px);
  box-shadow: 0 8px 20px rgba(45,212,191,0.4);
}

transform — bewegen, schalen, roteren

transform verplaatst, vergroot/verkleint of roteert een element — zonder de normale documentflow te beïnvloeden (andere elementen bewegen niet mee).

/* Verplaatsen */
transform: translateX(20px);   /* 20px naar rechts */
transform: translateY(-10px);  /* 10px omhoog */
transform: translate(20px, -10px); /* beide tegelijk */

/* Schalen */
transform: scale(1.1);         /* 10% groter */
transform: scale(0.9);         /* 10% kleiner */
transform: scaleX(2);          /* alleen horizontaal verdubbeld */

/* Roteren */
transform: rotate(45deg);      /* 45 graden met de klok mee */
transform: rotate(-90deg);     /* 90 graden tegen de klok in */

/* Combineren (ruimte-gescheiden) */
transform: translateY(-4px) scale(1.02) rotate(1deg);

/* Scherpheidsoptimalisatie bij animaties */
will-change: transform;        /* hint aan browser voor GPU-rendering */
translateY(-6px)
scale(1.3)
rotate(45deg)

@keyframes & animation

Met @keyframes definieer je een animatie-reeks. Met animation koppel je die aan een element.

/* Definieer de animatie */
@keyframes naam {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Of met percentages voor meer controle */
@keyframes bounce {
  0%   { transform: translateY(0); }
  40%  { transform: translateY(-20px); }
  60%  { transform: translateY(-10px); }
  80%  { transform: translateY(-4px); }
  100% { transform: translateY(0); }
}

/* Koppel aan element */
.element {
  animation: naam 0.6s ease forwards;
  /*         naam  duur  timing  fill-mode */
}

/* Alle animation-properties */
animation-name: naam;
animation-duration: 0.6s;
animation-timing-function: ease;
animation-delay: 0.2s;
animation-iteration-count: 1;        /* of: infinite */
animation-direction: normal;         /* of: reverse, alternate */
animation-fill-mode: forwards;       /* blijf in eindstand ⭐ */
animation-play-state: running;       /* of: paused */

pulse (infinite) · slide-in (eenmalig)

Veelgebruikte patronen & toegankelijkheid

Fade-in bij laden

@keyframes fade-in {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}
.sectie { animation: fade-in 0.5s ease forwards; }

/* Gestaggerd (met vertraging per item) */
.item:nth-child(1) { animation-delay: 0.1s; }
.item:nth-child(2) { animation-delay: 0.2s; }
.item:nth-child(3) { animation-delay: 0.3s; }

Spinner

@keyframes spin {
  to { transform: rotate(360deg); }
}
.spinner {
  width: 32px; height: 32px;
  border: 3px solid #374151;
  border-top-color: #2dd4bf;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

♿ prefers-reduced-motion

Sommige gebruikers worden misselijk van beweging. Respecteer hun systeemvoorkeur:

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

Performance: wat animeer je wel en niet?

Niet alle CSS-properties zijn even goedkoop om te animeren. De browser moet bij elke frame de pagina opnieuw renderen.

✅ Efficiënt (GPU)

  • transform (translate, scale, rotate)
  • opacity
  • filter

Deze worden op de GPU afgehandeld — geen layout recalculation nodig.

⚠️ Duur (reflow)

  • width / height
  • margin / padding
  • top / left
  • font-size

Gebruik transform: translate() in plaats van top/left.

Vuistregel: animeer bijna uitsluitend transform en opacity. Je kunt vrijwel elk visueel effect hiermee bereiken, en ze zijn altijd soepel.

Oefening 1 – Knop met hover-animatie

Maak een knop met een soepele hover-transition:
body: margin 0, padding 40px, background #0f172a, font-family sans-serif, display flex, gap 16px, flex-wrap wrap
.knop: padding 12px 28px, background #2dd4bf, color #0f172a, font-weight 700, border none, border-radius 10px, cursor pointer, font-size 15px, transition all 0.25s ease
.knop:hover: background #0d9488, color wit, transform translateY(-3px), box-shadow 0 8px 24px rgba(45,212,191,0.35)
.knop:active: transform translateY(0), box-shadow none

CSS

HTML

<button class="knop">Begin nu</button>
<button class="knop">Meer info</button>

Live voorbeeld

Oefening 2 – Laadspinner & fade-in

Maak een laadspinner en een fade-in animatie:
body: margin 0, padding 40px, background #0f172a, font-family sans-serif, display flex, flex-direction column, align-items center, gap 32px
@keyframes spin: van transform rotate(0deg) naar rotate(360deg)
.spinner: width 48px, height 48px, border 4px solid #1e293b, border-top-color #2dd4bf, border-radius 50%, animation spin 0.8s linear infinite
@keyframes fade-up: from opacity 0 + translateY(24px) → to opacity 1 + translateY(0)
.kaart: background #1e293b, color #e2e8f0, padding 24px 32px, border-radius 16px, animation fade-up 0.6s ease forwards, opacity 0

CSS

HTML

<div class="spinner"></div>
<div class="kaart">
  <h3 style="margin:0 0 8px">
    Geladen!
  </h3>
  <p style="margin:0;opacity:.7">
    Deze kaart fadedt in.
  </p>
</div>

Live voorbeeld

Quiz

🎬

Les 10 afgerond!

Transitions en animaties onder de knie! Nog twee lessen: variabelen & best practices, en het mini-project.

Volgende: Variabelen & best practices →