Opent in een nieuw tabblad

CSS-lab · Tekst-effecten

Letter-golf

Losse letters die in een golf op en neer bewegen en een cobalt schaduw achterlaten. Pure CSS met animation-delay en calc(), en toegankelijk opgezet.

  • Beginner
  • Pure CSS
  • MIT-licentie
  • @keyframes
  • animation-delay met calc()
  • custom properties (--i)
  • text-shadow
  • inline-block transforms
HTML
<div class="lwt-wrap">
  <h2 class="lwt-title">
    <span class="lwt-sr">Golfslag</span>
    <span class="lwt-letters" aria-hidden="true"><span style="--i:0">G</span><span style="--i:1">o</span><span style="--i:2">l</span><span style="--i:3">f</span><span style="--i:4">s</span><span style="--i:5">l</span><span style="--i:6">a</span><span style="--i:7">g</span></span>
  </h2>
  <p class="lwt-caption">Pure CSS · elke letter een eigen vertraging</p>
</div>
CSS
/* Letter-golf: dezelfde animatie, oplopende vertraging */
.lwt-wrap {
  --ink: #0C0C0D;
  --shadow: #2E5BFF;
  --lift: .28em;
  --speed: 1.8s;
  --stagger: 90ms;
  text-align: center;
  color: var(--ink);
}

.lwt-title {
  margin: 0;
  padding-top: .3em;
  font-family: "Arial Black", "Helvetica Neue", Impact, system-ui, sans-serif;
  font-size: clamp(52px, 12vw, 140px);
  font-weight: 900;
  line-height: 1;
  letter-spacing: -.02em;
  text-transform: uppercase;
}

/* Visueel verborgen, wel voorgelezen */
.lwt-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.lwt-letters {
  display: inline-flex;
}

.lwt-letters span {
  display: inline-block;
  animation: lwt-wave var(--speed) ease-in-out calc(var(--i, 0) * var(--stagger)) infinite;
}

/* Omhoog tot 30%, rust vanaf 60%; schaduw blijft op de plek */
@keyframes lwt-wave {
  0%, 60%, 100% {
    transform: translateY(0);
    text-shadow: 0 0 0 var(--shadow);
  }
  30% {
    transform: translateY(calc(var(--lift) * -1));
    text-shadow: 0 var(--lift) 0 var(--shadow);
  }
}

.lwt-caption {
  margin: 22px 0 0;
  font: 600 13px/1.4 ui-monospace, Menlo, Consolas, monospace;
  letter-spacing: .14em;
  text-transform: uppercase;
}

@media (prefers-reduced-motion: reduce) {
  .lwt-letters span { animation: none; }
}

Wat het is en waar je het gebruikt

Bij deze letter-golf beweegt elk teken van een kop kort omhoog en weer terug, telkens een fractie later dan de letter ervoor. Zo rolt er een golf door het woord. Op het hoogste punt blijft er een cobalt schaduw op de oorspronkelijke plek staan, waardoor het lijkt alsof de letter even loskomt van zijn eigen afdruk. Op de acid-lime achtergrond geeft dat een speels maar stevig beeld.

Het effect past bij een vrolijke campagne, een eventpagina, een laadscherm, een “bedankt”-pagina na een formulier of een kop in een sectie over creativiteit. Gebruik het voor één kort woord of een korte zin; bij een hele alinea wordt het onrustig.

Zo werkt het

  • Losse letters: elke letter staat in een eigen <span> met een inline variabele --i (0, 1, 2 enzovoort). De spans krijgen display: inline-block, anders werken transforms niet op inline-tekst.
  • Vertraging: alle letters delen dezelfde animatie. Alleen de vertraging verschilt: calc(var(--i, 0) * var(--stagger)). Daardoor beweegt elke letter later dan de vorige en ontstaat de golf.
  • De golf zelf: de keyframes lwt-wave tillen de letter bij 30% op met translateY(calc(var(--lift) * -1)) en laten hem vanaf 60% stil staan. Die rustpauze zorgt dat de golf duidelijk door het woord loopt in plaats van alles tegelijk te laten wiebelen.
  • Achterblijvende schaduw: tegelijk groeit de text-shadow naar 0 var(--lift) 0. Omdat de schaduw precies zo ver omlaag gaat als de letter omhoog, blijft hij op de oorspronkelijke plek staan.

Aanpassen

De variabelen staan op .lwt-wrap:

  • --ink: de kleur van de letters.
  • --shadow: de kleur van de achterblijvende afdruk.
  • --lift: hoe hoog de letters springen, in em zodat het meeschaalt met de lettergrootte.
  • --speed: de duur van één golf per letter.
  • --stagger: de tijd tussen twee letters. Hoger geeft een tragere, bredere golf.

Een ander woord? Maak per letter een span en nummer --i door. Pas ook de verborgen tekst in .lwt-sr aan.

Toegankelijkheid en browsersupport

Losse letters in spans worden door sommige screenreaders letter voor letter voorgelezen. Daarom staan de geanimeerde letters in een wrapper met aria-hidden="true". Het hele woord staat daarnaast in .lwt-sr, dat visueel verborgen is maar wel wordt voorgelezen. Zo blijft de kop een gewone, leesbare <h2>. Carbon op acid lime heeft een zeer hoog contrast. Met prefers-reduced-motion: reduce staan de letters stil. Wordt de inline --i verwijderd, dan valt var(--i, 0) terug op 0 en bewegen alle letters samen. Het effect werkt in alle actuele browsers.

Verder lezen

Speelse beweging werkt het best als kleine beloning op het juiste moment. Lees er meer over in ons artikel over microinteracties in UX. Wil je beweging die bij je merk past, bekijk dan interactief webdesign en animaties.