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: translateYtransition-delaycalc()custom properties per elementoverflow
<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>/* 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--azichtbaar en.rk-row--ber metposition: absoluteprecies overheen. De wrapper.rk-rollheeftoverflow: hidden, zodat alleen de regel in het midden zichtbaar is. - Elke letter is een
spanmetdisplay: inline-block, zodattransformwerkt. De letters in rij B starten optranslateY(110%), onder het zichtbare vlak. - Bij
:hoveren:focus-visiblegaan de letters van rij A naartranslateY(-110%)en die van rij B naar0. - De stagger komt van een inline variabele per letter (
style="--i:3") entransition-delay: calc(var(--i) * var(--stagger)). white-space: prezorgt 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.
Meer knoppen
