Kop wisselt per regel New
A three-line headline that exits upward out of a mask line by line every few seconds, making room for the next message. Hover pauses. For a hero with several promises.
Keukenstudio Veenendaal
Uw nieuwe keukenbinnen zes wekengeplaatst.
01 / 03
How to use it
- Paste the HTML where the text animations should appear.
- Add the CSS to your stylesheet. All classes are prefixed, so nothing clashes with your own styles.
- Add the JavaScript and call init() with the element that contains the HTML.
<!-- Kop wisselt per regel · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="hls"><span class="hls__kk">Keukenstudio Veenendaal</span><h4 class="hls__h" aria-live="polite"><span class="hls__l"><span class="hls__i">Uw nieuwe keuken</span></span><span class="hls__l"><span class="hls__i">binnen zes weken</span></span><span class="hls__l"><span class="hls__i hls__o">geplaatst.</span></span></h4>
<div class="hls__nav"><button class="hls__d is-on" type="button" aria-label="Boodschap 1"><span></span></button><button class="hls__d" type="button" aria-label="Boodschap 2"><span></span></button><button class="hls__d" type="button" aria-label="Boodschap 3"><span></span></button><span class="hls__ct">01 / 03</span></div></div>
</div>/* Kop wisselt per regel · NedDev · eigen werk. */
.hls{position:absolute;inset:0;background:#f4f3f1;color:#0a0a0a;font-family:'Switzer',system-ui,sans-serif;padding:18px 20px;display:flex;flex-direction:column;justify-content:center;gap:12px;container-type:inline-size}
.hls__kk{font:500 10px 'JetBrains Mono',monospace;letter-spacing:.12em;text-transform:uppercase;color:#6b6762}
.hls__h{margin:0;font:700 clamp(22px,8cqw,34px)/1.02 'Switzer',sans-serif;letter-spacing:-.045em}
.hls__l{display:block;overflow:hidden;padding-bottom:.06em}
.hls__i{display:block;white-space:nowrap}
.hls__o{color:#F5480F}
.hls__nav{display:flex;align-items:center;gap:6px}
.hls__d{appearance:none;border:0;padding:6px 0;background:none;cursor:pointer;width:34px}
.hls__d span{display:block;height:2px;background:#d6d1ca;border-radius:2px;position:relative;overflow:hidden}
.hls__d span::after{content:"";position:absolute;inset:0;background:#0a0a0a;transform:scaleX(0);transform-origin:left}
.hls__d.is-on span::after{animation:hls-fill 3.4s linear forwards}
.hls__d.is-done span::after{transform:scaleX(1)}
.hls.is-paused .hls__d.is-on span::after{animation-play-state:paused}
.hls__d:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.hls__ct{margin-left:6px;font:500 10px 'JetBrains Mono',monospace;color:#6b6762;font-variant-numeric:tabular-nums}
@keyframes hls-fill{to{transform:scaleX(1)}}
@media (prefers-reduced-motion:reduce){.hls__d.is-on span::after{animation:none;transform:scaleX(1)}}// Kop wisselt per regel · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
root=root.querySelector('.hls')||root;
var H=[['Uw nieuwe keuken','binnen zes weken','geplaatst.'],['Gemaakt in onze','eigen werkplaats','in Veenendaal.'],['Een vaste prijs,','ook als de muur','scheef blijkt.']];
var rm=matchMedia('(prefers-reduced-motion: reduce)').matches;
var lines=[].slice.call(root.querySelectorAll('.hls__l')),dots=[].slice.call(root.querySelectorAll('.hls__d')),ct=root.querySelector('.hls__ct');
var cur=0,busy=false,paused=false,timer=0,E='cubic-bezier(.7,0,.2,1)';
function set(n){if(busy||n===cur)return;busy=true;var prev=cur;cur=n;
dots.forEach(function(d,j){d.classList.toggle('is-on',j===n);d.classList.toggle('is-done',j<n);});ct.textContent='0'+(n+1)+' / 03';
lines.forEach(function(l,j){var i=l.firstChild;if(rm){i.textContent=H[n][j];return;}
var out=i.animate([{transform:'none'},{transform:'translateY(-108%)'}],{duration:420,delay:j*70,easing:E,fill:'forwards'});
out.onfinish=function(){i.textContent=H[n][j];var a=i.animate([{transform:'translateY(108%)'},{transform:'none'}],{duration:620,delay:j*70,easing:'cubic-bezier(.2,.8,.2,1)',fill:'forwards'});if(j===lines.length-1)a.onfinish=function(){busy=false;};};});
if(rm)busy=false;schedule();}
function schedule(){clearTimeout(timer);timer=setTimeout(tick,3400);}
function tick(){if(paused){timer=setTimeout(tick,300);return;}set((cur+1)%H.length);}
root.addEventListener('mouseenter',function(){paused=true;root.classList.add('is-paused');});
root.addEventListener('mouseleave',function(){paused=false;root.classList.remove('is-paused');});
dots.forEach(function(d,j){d.addEventListener('click',function(){set(j);});});
schedule();
}
init(document.querySelector('.jouw-container'));
More text animations
Seen something you like?
Add it to your selection and send it over. We build your site around it, in your brand.
Get in touch →