Opent in een nieuw tabblad

CSS-lab · Knoppen

Roll-over tekst-knop

Een knop waarvan het label bij hover letter voor letter omhoog wegrolt en van onderen weer terugkomt, in een golvende stagger.

  • Gemiddeld
  • Pure CSS
  • MIT-licentie
  • transform: translateY
  • transition-delay
  • calc()
  • custom properties per element
  • overflow
HTML
<button type="button" class="rk-btn" aria-label="Plan een call">
  <span class="rk-roll" aria-hidden="true">
    <span class="rk-row rk-row--a"><span style="--i:0">P</span><span style="--i:1">l</span><span style="--i:2">a</span><span style="--i:3">n</span><span style="--i:4"> </span><span style="--i:5">e</span><span style="--i:6">e</span><span style="--i:7">n</span><span style="--i:8"> </span><span style="--i:9">c</span><span style="--i:10">a</span><span style="--i:11">l</span><span style="--i:12">l</span></span>
    <span class="rk-row rk-row--b"><span style="--i:0">P</span><span style="--i:1">l</span><span style="--i:2">a</span><span style="--i:3">n</span><span style="--i:4"> </span><span style="--i:5">e</span><span style="--i:6">e</span><span style="--i:7">n</span><span style="--i:8"> </span><span style="--i:9">c</span><span style="--i:10">a</span><span style="--i:11">l</span><span style="--i:12">l</span></span>
  </span>
  <span class="rk-icon" aria-hidden="true">↗</span>
</button>
CSS
/* Roll-over tekst-knop - prefix .rk- */
.rk-btn {
  --accent: #C6FF3D;
  --hover: #F9F8F6;
  --ink: #0C0C0D;
  --speed: 0.45s;
  --stagger: 22ms;
  --ease: cubic-bezier(0.65, 0, 0.25, 1);
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 20px 32px;
  font: 900 1.05rem/1 "Arial Black", "Helvetica Neue", Impact, system-ui, sans-serif;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--accent);
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  transition: background-color var(--speed) var(--ease);
}

/* Venster van een regel hoog */
.rk-roll {
  position: relative;
  display: inline-block;
  overflow: hidden;
  line-height: 1.15;
  white-space: pre;
}

.rk-row {
  display: block;
}

/* Rij B ligt precies over rij A */
.rk-row--b {
  position: absolute;
  inset: 0;
}

/* Elke letter beweegt los, met vertraging per --i */
.rk-row span {
  display: inline-block;
  transition: transform var(--speed) var(--ease);
  transition-delay: calc(var(--i) * var(--stagger));
}

.rk-row--b span {
  transform: translateY(110%);
}

/* Hover en focus: A rolt weg, B rolt in */
.rk-btn:hover,
.rk-btn:focus-visible {
  background: var(--hover);
}

.rk-btn:hover .rk-row--a span,
.rk-btn:focus-visible .rk-row--a span {
  transform: translateY(-110%);
}

.rk-btn:hover .rk-row--b span,
.rk-btn:focus-visible .rk-row--b span {
  transform: translateY(0);
}

.rk-icon {
  font-size: 1.2em;
  transition: transform var(--speed) var(--ease);
}

.rk-btn:hover .rk-icon,
.rk-btn:focus-visible .rk-icon {
  transform: rotate(45deg);
}

.rk-btn:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 4px;
}

@media (prefers-reduced-motion: reduce) {
  .rk-btn,
  .rk-row span,
  .rk-icon {
    transition: none;
  }
}

Wat het is en waar je het gebruikt

Bij deze knop rolt het label weg. Beweeg je eroverheen, dan schuift elke letter omhoog uit beeld, terwijl dezelfde tekst van onderen weer binnenrolt. Omdat elke letter een fractie later vertrekt dan de vorige, loopt er een golf door het woord. Tegelijk verandert de achtergrond van acid lime naar off-white. Het is een kleine beloning voor de muisbeweging, zonder dat de knop van vorm verandert.

Het effect werkt goed in navigatie, als primaire CTA in een donkere header of op portfolio- en agency-sites waar details tellen. Gebruik het voor korte labels van één tot drie woorden. Bij lange zinnen duurt de golf te lang.

Zo werkt het

  • De knop bevat twee rijen met dezelfde letters: .rk-row--a zichtbaar en .rk-row--b er met position: absolute precies overheen. De wrapper .rk-roll heeft overflow: hidden, zodat alleen de regel in het midden zichtbaar is.
  • Elke letter is een span met display: inline-block, zodat transform werkt. De letters in rij B starten op translateY(110%), onder het zichtbare vlak.
  • Bij :hover en :focus-visible gaan de letters van rij A naar translateY(-110%) en die van rij B naar 0.
  • De stagger komt van een inline variabele per letter (style="--i:3") en transition-delay: calc(var(--i) * var(--stagger)).
  • white-space: pre zorgt dat de spatie tussen de woorden als eigen letter blijft staan.

Aanpassen

Op .rk-btn staan --accent (achtergrond in rust), --hover (achtergrond bij hover) en --ink (tekstkleur). Met --speed regel je hoe lang één letter onderweg is en met --stagger de vertraging tussen letters. Probeer 40ms voor een duidelijk zichtbare golf. --ease bepaalt het karakter van de beweging. Een ander label maak je door beide rijen aan te passen, de --i-waarden opnieuw te nummeren en de aria-label te wijzigen.

Toegankelijkheid en browsersupport

Een rij losse letters leest een schermlezer als losse tekens voor. Daarom krijgt de <button> een aria-label met het hele label en zijn beide rijen aria-hidden="true". Toetsenbordgebruikers zien hetzelfde effect bij focus, plus een outline in acid lime. Zwarte tekst op acid lime of off-white heeft een hoog contrast. Met prefers-reduced-motion staan de transities uit: de staat wisselt direct en de letters bewegen niet. De gebruikte technieken, inline custom properties met calc() in transition-delay, werken in alle actuele browsers.

Verder lezen

Meer van dit soort details vind je in ons artikel over CSS-knoppen en hover-effecten. Wil je je eigen site zo laten bewegen? Lees hoe we werken aan interactief webdesign en animaties.