KeurigOnline
Bestellen
Hosting
Domeinnaam
Ondersteuning
Ontdek

Op deze pagina

Blog / WordPress · · ~25 min lezen

CSS & Javascript loading animaties: 20 voorbeelden

Met de juiste animatie geef je gebruikers het gevoel dat er iets gebeurt, wat de ervaren wachttijd met wel 30% kan verkorten.

Geschreven door: Maarten Keizer Maarten Keizer
Deel dit artikel

Wist je dit? Gebruikers wachten gemiddeld slechts 2 seconden voordat ze de pagina verlaten. Hoe houd je bezoekers betrokken terwijl je content laadt?

De oplossing is visuele feedback via loading animaties. Met de juiste animatie geef je gebruikers het gevoel dat er iets gebeurt. Dit verkort de ervaren wachttijd met wel 30%.

In dit artikel ontdek je 20 praktische loading animaties met complete code voorbeelden. We starten met 7 custom animaties die speciaal ontwikkeld zijn voor optimale performance. Daarna volgen 13 extra voorbeelden georganiseerd per categorie.

Elke animatie komt met een live CodePen demo waar je direct mee kunt experimenteren. Klaar om je website levendiger te maken?

TL;DR — Welke loading animatie gebruik je wanneer?

  • Spinners → Korte loads onder 2 seconden (APIKeurigOnline zegtAPIKoppeling tussen verschillende systemen of software. calls, form submissions)
  • Skeleton screens → Content-heavy pagina's (feeds, product listings)
  • Progress bars → Uploads en downloads waar gebruikers exacte voortgang willen
  • Typing indicators → Chat interfaces en real-time communicatie

Scroll naar beneden voor 20 werkende CodePen voorbeelden met copy-paste code.

Definitie: Een loading animatie is een visuele indicator die gebruikers laat zien dat een website of applicatie bezig is met het laden van content. Dit kan een spinner, skeleton screen, progress bar of andere animatie zijn die feedback geeft tijdens wachttijd.

Abstracte illustratie van diverse CSS loading animaties: compositie met roterende spinners, stuiterende dots, progress bars met gradient flow, skeleton screen placeholders en 3D cube loaders - toont de verscheidenheid aan loading indicator types

20 voorbeelden van loading animaties

We gaan de animaties bekijken, maar ook de technische principes erachter. Je leert waarom bepaalde CSSKeurigOnline zegtCSSCSS is de stijltaal waarmee je de visuele opmaak en layout van HTML-pagina’s bepaalt. properties beter zijn voor performance en hoe je JavaScriptKeurigOnline zegtJavaScriptJavaScript is de browser- en server-scriptingtaal voor interactieve, asynchrone webapplicaties. gebruikt om animaties dynamisch te starten en stoppen.

We beginnen met 7 custom voorbeelden. Daarna volgen 13 gecategoriseerde varianten.

🎯 Loading animatie implementeren in 4 stappen

  1. Kies het juiste type — Spinner voor korte loads, skeleton voor content, progress bar voor uploads
  2. Kopieer de HTMLKeurigOnline zegtHTMLHTML is de programmeertaal voor het maken van webpagina’s. en CSS — Gebruik een van de 20 voorbeelden hieronder
  3. Pas kleuren aan — Wijzig de gradient kleuren naar je huisstijl
  4. Voeg JavaScript toe — Toon de loader bij page load of AJAX requests, verberg na completion

Custom loading animaties

1. Pulserende cirkel met gradient overlay

Een elegante pulserende cirkel die gebruikmaakt van CSS animations en radial gradients. Perfect voor moderne interfaces en subtiele feedback tijdens AJAX requests.

<div class="loader-container">
  <div class="pulse-loader"></div>
</div>
                
.loader-container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #1a1a2e;
}

.pulse-loader {
  width: 80px;
  height: 80px;
  background: radial-gradient(circle, #667eea 0%, #764ba2 100%);
  border-radius: 50%;
  animation: pulse 1.5s ease-in-out infinite;
  box-shadow: 0 0 40px rgba(102, 126, 234, 0.6);
}

@keyframes pulse {
  0%, 100% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.3);
    opacity: 0.7;
  }
}
                

Deze animatie gebruikt de volgende CSS technieken:

  • @keyframes pulse: Definieert de pulserende beweging met transform en opacity
  • radial-gradient: Creëert een mooie kleurovergang van binnen naar buiten
  • transform: scale(): Hardware-accelerated transformatie voor soepele animatie
  • animation timing: 1.5s ease-in-out zorgt voor natuurlijke beweging
  • box-shadow: Gloed-effect dat mee pulseert

Performance tip: transform en opacity zijn GPU-accelerated properties, waardoor deze animatie 60fps haalt op alle moderne browsers.

2. Drie-dots typing indicator met staggered delay

De bekende "typing indicator" animatie die je kent van chat apps. Drie dots die elkaar opvolgen met een subtiel bounce effect.

<div class="typing-loader">
  <span class="dot"></span>
  <span class="dot"></span>
  <span class="dot"></span>
</div>
                
body {
  margin: 0;
  overflow: hidden;

  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #0f0f23;
}

.typing-loader {
  display: flex;
  gap: 8px;
}

.dot {
  width: 12px;
  height: 12px;
  background: #00d9ff;
  border-radius: 50%;
  animation: bounce 1.4s infinite ease-in-out;
}

.dot:nth-child(1) {
  animation-delay: 0s;
}

.dot:nth-child(2) {
  animation-delay: 0.2s;
}

.dot:nth-child(3) {
  animation-delay: 0.4s;
}

@keyframes bounce {
  0%, 80%, 100% {
    transform: translateY(0) scale(1);
    opacity: 1;
  }
  40% {
    transform: translateY(-20px) scale(1.1);
    opacity: 0.8;
  }
}
                

Technische details:

  • animation-delay: Elke dot krijgt 0.2s vertraging voor het staggered effect
  • nth-child selector: Targeting van specifieke dots zonder extra classes
  • translateY: Verticale bounce beweging (GPU-accelerated)
  • scale(1.1): Subtiele groei op het hoogste punt
  • gap property: Moderne CSS voor spacing zonder margins

3. Circular progress bar met percentage counter

Een progress indicator die visueel toont hoeveel procent is geladen. Combineert SVG stroke-dashoffset met JavaScript voor real-time updates.

<div class="progress-container">
  <svg class="progress-ring" width="120" height="120">
    <circle class="progress-ring-bg" cx="60" cy="60" r="52"></circle>
    <circle class="progress-ring-circle" cx="60" cy="60" r="52"></circle>
  </svg>
  <div class="progress-text"><span id="percentage">0</span>%</div>
</div>
                
body {
  margin: 0;
  overflow: hidden;

  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #1e1e2e;
  font-family: 'Inter', sans-serif;
}

.progress-container {
  position: relative;
}

.progress-ring {
  transform: rotate(-90deg);
}

.progress-ring-bg {
  fill: none;
  stroke: #2d2d44;
  stroke-width: 8;
}

.progress-ring-circle {
  fill: none;
  stroke: #00ff88;
  stroke-width: 8;
  stroke-linecap: round;
  stroke-dasharray: 326.73;
  stroke-dashoffset: 326.73;
  transition: stroke-dashoffset 0.3s ease;
}

.progress-text {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 24px;
  font-weight: 700;
  color: #00ff88;
}
                
const circle = document.querySelector('.progress-ring-circle');
const percentageEl = document.getElementById('percentage');
const radius = 52;
const circumference = 2 * Math.PI * radius;

let progress = 0;

function updateProgress() {
  progress += 1;
  if (progress > 100) progress = 0;

  const offset = circumference - (progress / 100) * circumference;
  circle.style.strokeDashoffset = offset;
  percentageEl.textContent = progress;
}

setInterval(updateProgress, 50);
                

SVG en JavaScript technieken:

  • stroke-dasharray: Bepaalt lengte van de stroke (circumference van cirkel)
  • stroke-dashoffset: Offset die de "gevulde" lengte bepaalt
  • transform: rotate(-90deg): Start progress op 12 uur positie
  • stroke-linecap: round: Ronde uiteinden voor moderne look
  • JavaScript berekening: Offset = circumference - (progress × circumference / 100)

Real-world gebruik: Perfect voor file uploads, API requests of multi-step forms waar je exacte voortgang wilt tonen.

4. Skeleton screen voor content loading

Modern alternatief voor spinners. Toon een "skelet" van de content die gaat laden. Dit geeft gebruikers een preview en vermindert de ervaren wachttijd.

<div class="card-skeleton">
  <div class="skeleton-header">
    <div class="skeleton-avatar"></div>
    <div class="skeleton-author">
      <div class="skeleton-title"></div>
      <div class="skeleton-subtitle"></div>
    </div>
  </div>
  <div class="skeleton-image"></div>
  <div class="skeleton-text"></div>
  <div class="skeleton-text short"></div>
</div>
                
body {
  margin: 0;
  overflow: hidden;

  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  background: #f5f5f5;
  padding: 20px;
}

.card-skeleton {
  width: 100%;
  max-width: 400px;
  background: white;
  border-radius: 12px;
  padding: 20px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

.skeleton-header {
  display: flex;
  gap: 12px;
  margin-bottom: 16px;
}

.skeleton-avatar {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
}

.skeleton-author {
  flex: 1;
}

.skeleton-title {
  height: 16px;
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: 4px;
  margin-bottom: 8px;
}

.skeleton-subtitle {
  height: 12px;
  width: 60%;
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: 4px;
}

.skeleton-image {
  height: 200px;
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: 8px;
  margin-bottom: 16px;
}

.skeleton-text {
  height: 12px;
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: 4px;
  margin-bottom: 8px;
}

.skeleton-text.short {
  width: 70%;
}

@keyframes shimmer {
  0% {
    background-position: -200% 0;
  }
  100% {
    background-position: 200% 0;
  }
}
                

Skeleton screen principes:

  • linear-gradient met 3 stops: Creëert het "glans" effect
  • background-size: 200%: Maakt gradient 2x breder voor smooth animatie
  • background-position animatie: Beweegt gradient van links naar rechts
  • Layout matching: Skeleton volgt exact de structuur van echte content
  • Shimmer timing: 1.5s is ideaal — niet te snel, niet te traag

UX voordeel: Onderzoek toont aan dat skeleton screens de ervaren wachttijd met 30% verminderen vergeleken met spinners. Wil je meer weten over website snelheid testen? Bekijk onze gids met de 5 beste tools.

5. Rotating cube met 3D transforms

Een eye-catching 3D cube loader die roteert in alle richtingen. Gebruikt CSS 3D transforms voor een premium look.

<div class="scene">
  <div class="cube">
    <div class="cube-face front"></div>
    <div class="cube-face back"></div>
    <div class="cube-face right"></div>
    <div class="cube-face left"></div>
    <div class="cube-face top"></div>
    <div class="cube-face bottom"></div>
  </div>
</div>
                
body {
  margin: 0;
  overflow: hidden;

  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

.scene {
  width: 80px;
  height: 80px;
  perspective: 600px;
}

.cube {
  width: 100%;
  height: 100%;
  position: relative;
  transform-style: preserve-3d;
  animation: rotate 3s infinite linear;
}

.cube-face {
  position: absolute;
  width: 80px;
  height: 80px;
  background: rgba(255, 255, 255, 0.9);
  border: 2px solid rgba(255, 255, 255, 0.3);
  backdrop-filter: blur(10px);
}

.front  { transform: rotateY(0deg) translateZ(40px); }
.back   { transform: rotateY(180deg) translateZ(40px); }
.right  { transform: rotateY(90deg) translateZ(40px); }
.left   { transform: rotateY(-90deg) translateZ(40px); }
.top    { transform: rotateX(90deg) translateZ(40px); }
.bottom { transform: rotateX(-90deg) translateZ(40px); }

@keyframes rotate {
  0% {
    transform: rotateX(0deg) rotateY(0deg);
  }
  100% {
    transform: rotateX(360deg) rotateY(360deg);
  }
}
                

3D CSS eigenschappen:

  • perspective: 600px: Bepaalt de "camera afstand" voor 3D effect
  • transform-style: preserve-3d: Zorgt dat child elements in 3D space blijven
  • translateZ(): Positioneert elke face op juiste diepte (40px = halve breedte)
  • rotateX() en rotateY(): Creëert rotatie op beide assen tegelijk
  • backdrop-filter: Moderne glasmorphism effect op cube faces

6. Linear progress bar met gradient flow

Een moderne horizontale progress bar met vloeiend bewegende gradient. Ideaal voor file uploads of multi-step processen.

<div class="progress-wrapper">
  <div class="progress-label">Uploading...</div>
  <div class="progress-bar-container">
    <div class="progress-bar" id="progressBar"></div>
  </div>
  <div class="progress-stats">
    <span id="progressPercent">0%</span>
    <span>2.4 MB / 10 MB</span>
  </div>
</div>
                
body {
  margin: 0;
  overflow: hidden;

  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #2c2c3e;
  font-family: 'Inter', sans-serif;
}

.progress-wrapper {
  width: 400px;
  padding: 30px;
  background: #3a3a52;
  border-radius: 16px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}

.progress-label {
  font-size: 18px;
  font-weight: 600;
  color: #fff;
  margin-bottom: 12px;
}

.progress-bar-container {
  width: 100%;
  height: 8px;
  background: #2a2a3e;
  border-radius: 4px;
  overflow: hidden;
  margin-bottom: 12px;
}

.progress-bar {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, #667eea, #764ba2, #f093fb);
  background-size: 200% 100%;
  border-radius: 4px;
  animation: gradient-flow 2s linear infinite;
  transition: width 0.3s ease;
}

.progress-stats {
  display: flex;
  justify-content: space-between;
  font-size: 14px;
  color: #a0a0b8;
}

#progressPercent {
  color: #667eea;
  font-weight: 600;
}

@keyframes gradient-flow {
  0% {
    background-position: 0% 0%;
  }
  100% {
    background-position: 200% 0%;
  }
}
                
const progressBar = document.getElementById('progressBar');
const progressPercent = document.getElementById('progressPercent');

let progress = 0;

function simulateProgress() {
  if (progress < 100) {
    progress += Math.random() * 10;
    if (progress > 100) progress = 100;

    progressBar.style.width = progress + '%';
    progressPercent.textContent = Math.floor(progress) + '%';

    setTimeout(simulateProgress, 300);
  } else {
    setTimeout(() => {
      progress = 0;
      progressBar.style.width = '0%';
      progressPercent.textContent = '0%';
      simulateProgress();
    }, 1000);
  }
}

simulateProgress();
                

Progress bar technieken:

  • Gradient animation: background-position verschuift voor flow effect
  • width transition: Smooth groei van progress bar
  • JavaScriptKeurigOnline zegtJavaScriptJavaScript is de browser- en server-scriptingtaal voor interactieve, asynchrone webapplicaties. timing: Simuleert realistische upload met random increments
  • Dual indicators: Zowel percentage als absolute waarden
  • overflow: hidden: Houdt rounded corners intact tijdens animatie

7. Ripple effect loader met multiple waves

Concentrische cirkels die uitbreiden zoals water ripples. Elegant en subtiel, perfect voor achtergrond loading states.

<div class="ripple-container">
  <div class="ripple"></div>
  <div class="ripple"></div>
  <div class="ripple"></div>
</div>
                
body {
  margin: 0;
  overflow: hidden;

  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #0a0a0f;
}

.ripple-container {
  position: relative;
  width: 100px;
  height: 100px;
}

.ripple {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  border: 3px solid #00d9ff;
  animation: ripple 3s cubic-bezier(0, 0.2, 0.8, 1) infinite;
}

.ripple:nth-child(2) {
  animation-delay: 1s;
}

.ripple:nth-child(3) {
  animation-delay: 2s;
}

@keyframes ripple {
  0% {
    width: 0;
    height: 0;
    opacity: 1;
  }
  100% {
    width: 100px;
    height: 100px;
    opacity: 0;
  }
}
                

Ripple animatie principes:

  • Staggered delay: Elke ripple start met 1s vertraging voor golf-effect
  • cubic-bezier easing: Custom timing function voor natuurlijke versnelling
  • Opacity fade: Geleidelijke fade-out tijdens uitbreiden
  • Transform: translate(-50%, -50%): Centreert element vanaf top-left hoek
  • border vs background: Border gebruikt minder pixels voor betere performance

Variatie tip: Verander border naar box-shadow voor glow ripples. Of gebruik meerdere kleuren voor een rainbow effect.

Spinner variaties

8. Classic spinning border met gradient

De meest herkenbare loader. Een roterende cirkel met partial border. Moderne twist met gradient kleuren.

<div class="spinner"></div>
                
body {
  margin: 0;
  overflow: hidden;

  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #16161d;
}

.spinner {
  width: 60px;
  height: 60px;
  border: 6px solid rgba(255, 255, 255, 0.1);
  border-top-color: #667eea;
  border-right-color: #764ba2;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}
                

Spinner basics:

  • Partial border: Transparante borders met gekleurde top/right
  • 0.8s duration: Snelle rotatie voelt responsief
  • linear timing: Constante snelheid zonder versnelling

9. Dual-ring rotating loader

Twee concentrische ringen die in tegengestelde richting roteren voor een hypnotiserend effect.

<div class="dual-ring-container">
  <div class="ring outer"></div>
  <div class="ring inner"></div>
</div>
                
body {
  margin: 0;
  overflow: hidden;

  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #1a1a2e;
}

.dual-ring-container {
  position: relative;
  width: 80px;
  height: 80px;
}

.ring {
  position: absolute;
  border-radius: 50%;
  border: 4px solid transparent;
}

.outer {
  width: 80px;
  height: 80px;
  border-top-color: #00d9ff;
  border-right-color: #00d9ff;
  animation: spin 1.2s linear infinite;
}

.inner {
  width: 50px;
  height: 50px;
  top: 15px;
  left: 15px;
  border-top-color: #ff006e;
  border-left-color: #ff006e;
  animation: spin-reverse 1.2s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

@keyframes spin-reverse {
  to { transform: rotate(-360deg); }
}
                

Dual rotation techniek:

  • Negative rotation: -360deg voor tegengestelde richting
  • Positioning: Inner ring gecentreerd met absolute positioning
  • Contrast colors: Verschillende kleuren maken rotaties zichtbaar

10. Bouncing balls met physics-based motion

Drie ballen die springen met realistische physics, zwaartekracht en elasticity.

<div class="bouncing-balls">
  <div class="ball"></div>
  <div class="ball"></div>
  <div class="ball"></div>
</div>
                
body {
  margin: 0;
  overflow: hidden;

  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #2d2d44;
}

.bouncing-balls {
  display: flex;
  gap: 12px;
  align-items: flex-end;
  height: 80px;
}

.ball {
  width: 20px;
  height: 20px;
  background: linear-gradient(135deg, #667eea, #764ba2);
  border-radius: 50%;
  animation: bounce 0.6s cubic-bezier(0.28, 0.84, 0.42, 1) infinite;
}

.ball:nth-child(1) {
  animation-delay: 0s;
}

.ball:nth-child(2) {
  animation-delay: 0.2s;
}

.ball:nth-child(3) {
  animation-delay: 0.4s;
}

@keyframes bounce {
  0%, 100% {
    transform: translateY(0) scaleY(1);
  }
  50% {
    transform: translateY(-60px) scaleY(1);
  }
  90% {
    transform: translateY(0) scaleY(0.8) scaleX(1.2);
  }
}
                

Physics simulation:

  • cubic-bezier easing: Imiteert zwaartekracht en bounce
  • scaleY(0.8) scaleX(1.2): Squash effect bij landing
  • 90% keyframe: Impact moment net voor 100%

Text-based loading indicators

11. Animated "Loading..." met dots

Tekst-based loader waarbij dots één voor één verschijnen en verdwijnen. Geen afbeeldingen nodig.

<div class="loading-text">
  Loading<span class="dots"><span>.</span><span>.</span><span>.</span></span>
</div>
                
body {
  margin: 0;
  overflow: hidden;

  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #0f0f23;
  font-family: 'Courier New', monospace;
}

.loading-text {
  font-size: 32px;
  color: #00d9ff;
  font-weight: 700;
}

.dots span {
  animation: blink 1.4s infinite;
  opacity: 0;
}

.dots span:nth-child(1) {
  animation-delay: 0s;
}

.dots span:nth-child(2) {
  animation-delay: 0.2s;
}

.dots span:nth-child(3) {
  animation-delay: 0.4s;
}

@keyframes blink {
  0%, 20% {
    opacity: 0;
  }
  40% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}
                

Text animation voordelen:

  • Accessibility: Screen readers kunnen text lezen
  • No images: Laadt instant, geen extra HTTPKeurigOnline zegtHTTPHTTP is het protocol waarmee webclients en -servers gestructureerd data uitwisselen via requests en responses. requests
  • Customizable: Verander font, size, color moeiteloos

12. Glitch text effect loader

Cyberpunk-stijl glitch effect op loading text. Perfect voor tech en gaming websites.

<div class="glitch" data-text="LOADING">LOADING</div>
                
body {
  margin: 0;
  overflow: hidden;

  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #000;
  overflow: hidden;
}

.glitch {
  position: relative;
  font-size: 64px;
  font-weight: 900;
  color: #fff;
  letter-spacing: 8px;
  animation: glitch-skew 1s infinite;
}

.glitch::before,
.glitch::after {
  content: attr(data-text);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.glitch::before {
  left: 2px;
  text-shadow: -2px 0 #ff00de;
  clip: rect(24px, 550px, 90px, 0);
  animation: glitch-anim 2s infinite linear alternate-reverse;
}

.glitch::after {
  left: -2px;
  text-shadow: -2px 0 #00fff9;
  clip: rect(85px, 550px, 140px, 0);
  animation: glitch-anim 3s infinite linear alternate-reverse;
}

@keyframes glitch-skew {
  0% {
    transform: skew(0deg);
  }
  10% {
    transform: skew(-2deg);
  }
  20% {
    transform: skew(2deg);
  }
  30% {
    transform: skew(0deg);
  }
}

@keyframes glitch-anim {
  0% {
    clip: rect(33px, 9999px, 94px, 0);
  }
  20% {
    clip: rect(10px, 9999px, 73px, 0);
  }
  40% {
    clip: rect(85px, 9999px, 40px, 0);
  }
  60% {
    clip: rect(65px, 9999px, 119px, 0);
  }
  80% {
    clip: rect(24px, 9999px, 62px, 0);
  }
  100% {
    clip: rect(91px, 9999px, 34px, 0);
  }
}
                

Glitch effect techniek:

  • attr(data-text): Duplicate text via CSS content property
  • clip: rect(): Toont alleen specifieke delen van pseudo-elements
  • text-shadow kleuren: Cyan en magenta voor RGB split effect
  • Random clip values: Verschillende heights per keyframe

13. Percentage counter met easing

Toon exacte loading percentage met smooth counting animatie van 0 tot 100.

<div class="counter-wrapper">
  <div class="counter" id="counter">0</div>
  <div class="counter-label">%</div>
</div>
                
body {
  margin: 0;
  overflow: hidden;

  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
  font-family: 'Inter', sans-serif;
}

.counter-wrapper {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.counter {
  font-size: 120px;
  font-weight: 900;
  color: #fff;
  line-height: 1;
  text-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}

.counter-label {
  font-size: 48px;
  color: rgba(255, 255, 255, 0.8);
  font-weight: 700;
}
                
const counter = document.getElementById('counter');
const duration = 3000; // 3 seconds
const start = 0;
const end = 100;
const startTime = Date.now();

function easeOutCubic(t) {
  return 1 - Math.pow(1 - t, 3);
}

function animateCounter() {
  const now = Date.now();
  const elapsed = now - startTime;
  const progress = Math.min(elapsed / duration, 1);

  const easedProgress = easeOutCubic(progress);
  const current = Math.floor(start + (end - start) * easedProgress);

  counter.textContent = current;

  if (progress < 1) {
    requestAnimationFrame(animateCounter);
  } else {
    // Reset after completion
    setTimeout(() => {
      counter.textContent = '0';
      animateCounter();
    }, 1000);
  }
}

animateCounter();
                

Counter animatie principes:

  • requestAnimationFrame: Sync met browser refresh rate voor smoothness
  • Easing function: easeOutCubic voor natuurlijke versnelling/vertraging
  • Time-based: Gebruikt elapsed time, niet frame count
  • Math.floor(): Voorkomt decimal numbers in display

Advanced progress indicators

14. Multi-step progress indicator

Visuele weergave van multi-step processen. Met actieve state indicators.

<div class="steps-container">
  <div class="step active">
    <div class="step-number">1</div>
    <div class="step-label">Account</div>
  </div>
  <div class="step-line"></div>
  <div class="step active">
    <div class="step-number">2</div>
    <div class="step-label">Payment</div>
  </div>
  <div class="step-line"></div>
  <div class="step">
    <div class="step-number">3</div>
    <div class="step-label">Confirm</div>
  </div>
</div>
                
body {
  margin: 0;
  overflow: hidden;

  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #f8f9fa;
  font-family: 'Inter', sans-serif;
}

.steps-container {
  display: flex;
  align-items: center;
  gap: 0;
}

.step {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.step-number {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: #e0e0e0;
  color: #999;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  font-weight: 700;
  transition: all 0.3s ease;
}

.step.active .step-number {
  background: linear-gradient(135deg, #667eea, #764ba2);
  color: white;
  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
}

.step-label {
  font-size: 14px;
  color: #999;
  font-weight: 500;
  transition: color 0.3s ease;
}

.step.active .step-label {
  color: #333;
  font-weight: 600;
}

.step-line {
  width: 80px;
  height: 3px;
  background: #e0e0e0;
  margin: 0 -8px 20px -8px;
}
                

Multi-step design:

  • .active class: JavaScript toggled state voor current step
  • Gradient background: Visuele highlight voor actieve steps
  • Transition delays: Smooth state changes

15. Indeterminate progress bar (unknown duration)

Voor processen waar je niet weet hoelang het duurt, gebruik een oneindige bewegende bar.

<div class="indeterminate-container">
  <div class="indeterminate-bar"></div>
</div>
                
body {
  margin: 0;
  overflow: hidden;

  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #1a1a2e;
}

.indeterminate-container {
  width: 300px;
  height: 4px;
  background: rgba(255, 255, 255, 0.1);
  border-radius: 2px;
  overflow: hidden;
}

.indeterminate-bar {
  width: 40%;
  height: 100%;
  background: linear-gradient(90deg, transparent, #00d9ff, transparent);
  animation: indeterminate 1.5s cubic-bezier(0.65, 0.05, 0.36, 1) infinite;
}

@keyframes indeterminate {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(350%);
  }
}
                

Indeterminate techniek:

  • translateX range: -100% tot 350% voor volledige traverse
  • Gradient with transparancy: Fade in/out effect
  • overflow: hidden: Verbergt bar buiten container

16. Stacked bars met multiple processes

Toon meerdere simultane processen met individuele progress bars.

<div class="multi-progress">
  <div class="process">
    <div class="process-label">Uploading files</div>
    <div class="process-bar">
      <div class="process-fill" style="width: 75%"></div>
    </div>
  </div>
  <div class="process">
    <div class="process-label">Processing images</div>
    <div class="process-bar">
      <div class="process-fill" style="width: 45%"></div>
    </div>
  </div>
  <div class="process">
    <div class="process-label">Generating thumbnails</div>
    <div class="process-bar">
      <div class="process-fill" style="width: 20%"></div>
    </div>
  </div>
</div>
                
body {
  margin: 0;
  overflow: hidden;

  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #2c2c3e;
  font-family: 'Inter', sans-serif;
}

.multi-progress {
  width: 400px;
  padding: 24px;
  background: #3a3a52;
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.process-label {
  font-size: 14px;
  color: #a0a0b8;
  margin-bottom: 8px;
}

.process-bar {
  width: 100%;
  height: 6px;
  background: #2a2a3e;
  border-radius: 3px;
  overflow: hidden;
}

.process-fill {
  height: 100%;
  background: linear-gradient(90deg, #667eea, #764ba2);
  border-radius: 3px;
  transition: width 0.5s ease;
}
                

Multi-process UI:

  • Stacked layout: flex-direction: column voor vertical stack
  • Individual widths: Elke bar heeft eigen percentage
  • Semantic labels: Duidelijke communicatie wat er gebeurt

Creative & experimentele loaders

17. DNA helix rotating loader

Dubbele helix structuur die roteert. Visueel interessant en uniek.

<div class="dna-loader">
  <div class="strand">
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
  </div>
  <div class="strand">
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
  </div>
</div>
                
body {
  margin: 0;
  overflow: hidden;

  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #0a0a0f;
}

.dna-loader {
  position: relative;
  width: 100px;
  height: 100px;
}

.strand {
  position: absolute;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  animation: rotate 2s linear infinite;
}

.strand:nth-child(2) {
  animation-delay: -1s;
}

.dot {
  width: 12px;
  height: 12px;
  background: linear-gradient(135deg, #00d9ff, #0088ff);
  border-radius: 50%;
  box-shadow: 0 0 10px #00d9ff;
}

@keyframes rotate {
  0% {
    transform: rotateY(0deg);
  }
  100% {
    transform: rotateY(360deg);
  }
}
                

3D rotation:

  • rotateY(360deg): Rotatie op Y-as voor helix effect
  • animation-delay: -1s: Start tweede strand halverwege
  • glow effect: box-shadow in matching color

18. Heartbeat monitor met EKG line

Geanimeerde hartslag lijn zoals je ziet op medische monitors.

<div class="ekg-container">
  <svg class="ekg" viewBox="0 0 200 60">
    <polyline class="ekg-line" points="0,30 40,30 45,10 50,50 55,30 200,30" />
  </svg>
</div>
                
body {
  margin: 0;
  overflow: hidden;

  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #0a0a0a;
}

.ekg-container {
  width: 400px;
  height: 120px;
  background: #1a1a1a;
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 0 20px rgba(0, 255, 136, 0.2);
}

.ekg {
  width: 100%;
  height: 100%;
}

.ekg-line {
  fill: none;
  stroke: #00ff88;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 200;
  stroke-dashoffset: 200;
  animation: ekg-pulse 2s linear infinite;
  filter: drop-shadow(0 0 4px #00ff88);
}

@keyframes ekg-pulse {
  0% {
    stroke-dashoffset: 200;
  }
  100% {
    stroke-dashoffset: 0;
  }
}
                

SVG line animation:

  • stroke-dasharray & dashoffset: Tekent lijn geleidelijk
  • polyline points: Definieert EKG vorm
  • filter: drop-shadow: SVG glow effect

19. Matrix rain loader

Iconic Matrix-style vallende karakters als loading indicator.

<div class="matrix-container">
  <div class="matrix-column">
    <span>1</span><span>0</span><span>1</span>
    <span>0</span><span>1</span>
  </div>
  <div class="matrix-column">
    <span>0</span><span>1</span><span>0</span>
    <span>1</span>
  </div>
  <div class="matrix-column">
    <span>1</span><span>1</span><span>0</span>
    <span>0</span><span>1</span>
  </div>
  <div class="matrix-column">
    <span>0</span><span>1</span><span>1</span>
    <span>0</span>
  </div>
</div>
                
body {
  margin: 0;
  overflow: hidden;

  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #000;
  overflow: hidden;
}

.matrix-container {
  display: flex;
  gap: 20px;
  font-family: 'Courier New', monospace;
  font-size: 20px;
}

.matrix-column {
  display: flex;
  flex-direction: column;
  animation: fall 3s linear infinite;
}

.matrix-column:nth-child(1) { animation-delay: 0s; }
.matrix-column:nth-child(2) { animation-delay: 0.5s; }
.matrix-column:nth-child(3) { animation-delay: 1s; }
.matrix-column:nth-child(4) { animation-delay: 1.5s; }

.matrix-column span {
  color: #00ff41;
  opacity: 0;
  animation: fade 0.5s ease-in-out infinite;
}

.matrix-column span:nth-child(1) { animation-delay: 0s; }
.matrix-column span:nth-child(2) { animation-delay: 0.2s; }
.matrix-column span:nth-child(3) { animation-delay: 0.4s; }
.matrix-column span:nth-child(4) { animation-delay: 0.6s; }
.matrix-column span:nth-child(5) { animation-delay: 0.8s; }

@keyframes fall {
  0% {
    transform: translateY(-100%);
  }
  100% {
    transform: translateY(100vh);
  }
}

@keyframes fade {
  0%, 100% {
    opacity: 0;
  }
  50% {
    opacity: 1;
  }
}
                

Matrix effect:

  • Staggered columns: Verschillende animation-delays
  • translateY(100vh): Beweegt van boven naar beneden
  • Fade animation: Characters flikkeren tijdens val

20. Morphing shapes loader

Shape die morfheert tussen cirkel, vierkant en driehoek is hypnotiserend en modern.

<div class="morph-loader"></div>
                
body {
  margin: 0;
  overflow: hidden;

  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

.morph-loader {
  width: 80px;
  height: 80px;
  background: white;
  animation: morph 3s ease-in-out infinite;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}

@keyframes morph {
  0% {
    border-radius: 50%;
    transform: rotate(0deg);
  }
  33% {
    border-radius: 0%;
    transform: rotate(120deg);
  }
  66% {
    border-radius: 50% 0% 50% 0%;
    transform: rotate(240deg);
  }
  100% {
    border-radius: 50%;
    transform: rotate(360deg);
  }
}
                

Shape morphing:

  • border-radius variaties: 50% = cirkel, 0% = vierkant
  • 50% 0% 50% 0%: Creëert bladachtige vorm
  • Simultane rotation: Transform + border-radius = vloeiende morphing
  • ease-in-out timing: Natuurlijke transitions tussen shapes

Variatie tip: Experimenteer met verschillende border-radius waarden voor unieke shapes.

Accessibility: respecteer prefers-reduced-motion

Niet iedereen houdt van animaties. Sommige gebruikers ervaren misselijkheid, duizeligheid of afleiding door bewegende elementen. Dit heet vestibular motion sensitivity en treft naar schatting 35% van volwassenen boven de 40 jaar.

Moderne browsers ondersteunen de prefers-reduced-motion media query. Hiermee kun je animaties uitschakelen of vereenvoudigen voor gebruikers die dit hebben ingesteld:

/* Standaard: animatie actief */
.loader {
  animation: spin 1s linear infinite;
}

/* Voor gebruikers die reduced motion prefereren */
@media (prefers-reduced-motion: reduce) {
  .loader {
    animation: none;
    /* Toon statische indicator of subtiele opacity pulse */
    opacity: 0.7;
  }
}

Best practices voor toegankelijke loading animaties:

  • Gebruik altijd prefers-reduced-motion om animaties uit te schakelen
  • Voeg aria-label="Laden..." toe aan je loader element
  • Overweeg aria-live="polite" voor screen readers
  • Vermijd flitsende animaties (max 3 flitsen per seconde volgens WCAG 2.3.1)

Alle 20 voorbeelden in dit artikel zijn getest op Chrome 120, Firefox 121 en Safari 17. Elke animatie haalt 60fps op mid-range devices dankzij GPU-accelerated properties (transform, opacity).

Vergelijkingstabel: welke loader voor welke situatie?

Kies de juiste loading animatie op basis van je use case:

Type Gebruik wanneer Duur Voorbeelden
Spinner Korte, onbepaalde wachttijd < 2 sec APIKeurigOnline zegtAPIKoppeling tussen verschillende systemen of software. calls, form submit, button click
Skeleton screen Content layout bekend 1-5 sec Feed items, cards, product listings
Progress bar Voortgang meetbaar 5+ sec File upload, download, installatie
Typing indicator Wachten op andere partij Onbepaald Chat, AI responses, live updates
Multi-step Meerdere stappen in proces Varies Checkout, onboarding, wizards

Vuistregel: Hoe langer de wachttijd, hoe meer informatie je moet geven. Onder 2 seconden volstaat een simpele spinner. Boven 5 seconden wil de gebruiker exacte voortgang zien.

Animation tools en libraries die je moet kennen

Na het bekijken van deze 20 voorbeelden wil je misschien meer mogelijkheden verkennen. Hier zijn drie essentiële tools die je helpen bij het bouwen van loading animaties.

GSAP (GreenSock Animation Platform)

GSAP is dé JavaScript animation library voor professionele animaties. Met 11 miljoen downloads per maand en 16k+ GitHubKeurigOnline zegtGithubGitHub is een platform voor versiebeheer en samenwerking aan code. Onze pakketten ondersteunen SSH en git. stars is het de industry standard.

GSAP biedt timeline control, easing functions en performance optimization out-of-the-box. Perfect voor complexe loading sequences waar je meerdere elementen moet orchestreren.

De library is slechts 50KB (gzipped) maar levert GPU-accelerated animaties die 20x sneller zijn dan jQuery. Ideaal voor production-ready loading states.

Lottie

Lottie van Airbnb rendert After Effects animaties real-time. Designers maken complexe animaties in After Effects en exporteren als JSONKeurigOnline zegtJSONJSON is een lichtgewicht dataformaat voor het uitwisselen van gegevens tussen systemen.. Developers embedden ze met 3 regels code.

De library is slechts 35KB maar ondersteunt kleur changes, playback control en interactieve triggers. Perfect voor custom brand animaties zonder handmatig CSS te schrijven.

Lottie files zijn vector-based, dus ze schalen perfect naar elke schermgrootte zonder kwaliteitsverlies. Cruciaal voor responsive designs.

CSS Loaders

CSS Loaders is een verzameling van 600+ pure CSSKeurigOnline zegtCSSCSS is de stijltaal waarmee je de visuele opmaak en layout van HTML-pagina’s bepaalt. loading animaties. Elk voorbeeld komt met copy-paste code en live preview.

De collectie gebruikt alleen CSS zonder JavaScript, wat betekent instant loading en zero dependencies. Sorteer op style (spinner, bars, dots) of complexity (simple, medium, advanced).

Alle loaders zijn geoptimaliseerd voor performance met GPU-accelerated properties (transform, opacity). Perfect startpunt voor je eigen custom variaties.

Conclusie

Loading animaties zijn onmisbaar voor moderne websites, of niet?

Een goed gekozen loading animatie verbetert de gebruikerservaring drastisch. Maar overdrijf niet. Te veel animaties, te lange duur of te complexe effecten veroorzaken irritatie. De beste loading indicator is er één die je gebruiker nauwelijks opmerkt omdat je website razendsnel laadt.

Gebruik de 20 voorbeelden uit dit artikel als inspiratie en pas ze aan voor jouw brand en doelgroep. Start met simpele spinners voor korte loads (< 2 seconden). Gebruik skeleton screens voor content-heavy paginas en reserveer progress bars voor file uploads waar gebruikers exacte voortgang willen zien.

Test altijd op echte devices en meet of je animatie de ervaren wachttijd daadwerkelijk verkort. Bekijk ook onze andere frontend tutorials: CSS button designs met 20 voorbeelden en .htaccess snippets voor snellere websites.

Keurig Online

Bij KeurigOnline zorgen we ervoor dat je loading animaties zo kort mogelijk draaien. Onze LiteSpeed-servers met NVMeKeurigOnline zegtNVMeNVMe is ultrasnelle SSD-opslag die websites tot 6x sneller maakt dan traditionele opslag.-opslag leveren laadtijden onder 0,8s, waardoor je gebruikers minder wachten en meer converteren.

Wil je hulp bij het optimaliseren van je website performance? Onze support uit Groningen staat klaar met 77% reactietijd onder 1 minuut.

Veelgestelde vragen over loading animaties

Wat is een loading animatie?

Een loading animatie is een visuele indicator die gebruikers laat zien dat een website of applicatie bezig is met het laden van content. Dit kan een roterende spinner, skeleton screen, progress bar of typing indicator zijn. Loading animaties geven feedback tijdens wachttijd en verminderen de ervaren laadtijd met gemiddeld 30%.

Welke CSS properties gebruik je voor een loading animatie?

De belangrijkste CSS properties voor loading animaties zijn @keyframes voor de animatie definitie, animation voor timing en herhaling, en transform met opacity voor GPU-accelerated beweging. Gebruik altijd transform (rotate, scale, translate) in plaats van width/height voor 60fps performance.

Wat is het verschil tussen een spinner en een skeleton screen?

Een spinner is een roterende indicator voor korte, onbekende wachttijden (onder 2 seconden). Een skeleton screen toont een placeholder van de content layout en is beter voor langere loads (1-5 seconden) waar de structuur bekend is. Onderzoek toont dat skeleton screens de ervaren wachttijd met 30% verkorten vergeleken met spinners.

Hoe maak je een CSS spinner zonder JavaScript?

Een CSS spinner maak je met een cirkel (border-radius: 50%) met een gedeeltelijk gekleurde border (border-top-color) en een oneindige rotate animatie. De basis code is: .spinner { border: 4px solid #f3f3f3; border-top: 4px solid #3498db; border-radius: 50%; animation: spin 1s linear infinite; } met @keyframes spin { to { transform: rotate(360deg); } }.

Wanneer gebruik je een progress bar in plaats van een spinner?

Gebruik een progress bar wanneer je de exacte voortgang kunt meten, zoals bij file uploads, downloads of multi-step formulieren. Progress bars zijn ideaal voor processen langer dan 5 seconden. Voor onbekende duur gebruik je een indeterminate progress bar met een bewegende gradient in plaats van een vaste percentage.

Hoe maak je een loading animatie toegankelijk?

Maak loading animaties toegankelijk door de prefers-reduced-motion media query te gebruiken om animaties uit te schakelen voor gevoelige gebruikers. Voeg aria-label="Laden..." toe aan het loader element en gebruik aria-live="polite" voor screen readers. Vermijd flitsende animaties (max 3 per seconde volgens WCAG 2.3.1).

Welke loading animatie is het beste voor website performance?

De beste loading animaties voor performance gebruiken alleen transform en opacity properties, omdat deze GPU-accelerated zijn. Vermijd animaties op width, height, margin of padding. Pure CSS animaties zijn sneller dan JavaScriptKeurigOnline zegtJavaScriptJavaScript is de browser- en server-scriptingtaal voor interactieve, asynchrone webapplicaties.. Een simpele spinner met transform: rotate() is de meest performante optie met minimale impact op Core Web VitalsKeurigOnline zegtCore Web VitalsCore Web Vitals zijn Google's belangrijkste metrics voor website-ervaring en snelheid..

Hoe toon en verberg je een loading animatie met JavaScript?

Toon een loader door het element zichtbaar te maken met document.getElementById('loader').style.display = 'flex' bij het starten van een AJAX request. Verberg na completion met style.display = 'none' in de callback of .then() van een fetch. Gebruik CSS transitions voor smooth fade-in/fade-out effecten.

Wat zijn de beste libraries voor loading animaties?

De drie beste libraries zijn GSAP (GreenSock) voor complexe sequenties met 50KB footprint, Lottie van Airbnb voor After Effects animaties als JSONKeurigOnline zegtJSONJSON is een lichtgewicht dataformaat voor het uitwisselen van gegevens tussen systemen. (35KB), en CSS Loaders voor 600+ pure CSS voorbeelden zonder dependencies. Voor simpele loaders is pure CSS vaak voldoende en sneller dan een library.

Hoe lang mag een loading animatie duren?

Gebruikers accepteren maximaal 2-3 seconden wachttijd voordat ze afhaken. Voor loads onder 1 seconde is vaak geen loader nodig. Tussen 1-3 seconden gebruik je een spinner. Boven 3 seconden toon je een progress bar met percentage of geef feedback over wat er gebeurt. De beste oplossing is altijd je website sneller maken zodat loaders niet nodig zijn.

Bronnen

Laatst gecontroleerd: december 2024