Cursor Ring Follower
Dual-layer cursor: dot volgt direct, ring trailt met lerp en groeit op hover.
beweeg hier
Zo gebruik je het
- Plak de HTML op de plek waar het onderdeel moet komen.
- Zet de CSS in je stylesheet. Alle klassen hebben een eigen voorvoegsel, dus niets botst met je eigen opmaak.
- Voeg de JavaScript toe en roep init() aan met het element waar de HTML in staat.
<!-- Cursor Ring Follower · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="crf-stage"><div class="crf-grid"><button class="crf-hot">Hover</button><button class="crf-hot">Drag</button><button class="crf-hot">Click</button></div><div class="crf-ring"></div><div class="crf-dot"></div><span class="crf-hint">beweeg hier</span></div>
</div>/* Cursor Ring Follower · NedDev · eigen werk. */
.crf-stage{position:absolute;inset:0;overflow:hidden;cursor:none;background:#fff;font-family:'Switzer',system-ui,sans-serif;display:flex;align-items:center;justify-content:center}
.crf-grid{display:flex;gap:14px}
.crf-hot{cursor:none;padding:14px 22px;border:1px solid rgba(10,10,10,.12);background:#fff;color:#0a0a0a;border-radius:12px;font-size:14px;font-weight:600;transition:background .2s,color .2s}
.crf-hot:hover{background:#0a0a0a;color:#fff}
.crf-ring{position:absolute;top:0;left:0;width:38px;height:38px;border:1.5px solid #F5480F;border-radius:50%;pointer-events:none;transform:translate(-50%,-50%);transition:width .25s,height .25s,background .25s;z-index:5;mix-blend-mode:multiply}
.crf-dot{position:absolute;top:0;left:0;width:6px;height:6px;background:#0a0a0a;border-radius:50%;pointer-events:none;transform:translate(-50%,-50%);z-index:6}
.crf-stage.is-hot .crf-ring{width:60px;height:60px;background:rgba(245,72,15,.08)}
.crf-hint{position:absolute;bottom:14px;left:14px;font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:rgba(10,10,10,.4)}
@media(hover:none){.crf-ring,.crf-dot{display:none}.crf-stage{cursor:auto}.crf-hot{cursor:pointer}}// Cursor Ring Follower · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
root=root.querySelector('.crf-stage')||root;var ring=root.querySelector('.crf-ring'),dot=root.querySelector('.crf-dot');var mx=0,my=0,rx=0,ry=0;var reduce=matchMedia('(prefers-reduced-motion:reduce)').matches;
root.addEventListener('mousemove',function(e){var r=root.getBoundingClientRect();mx=e.clientX-r.left;my=e.clientY-r.top;dot.style.transform='translate('+mx+'px,'+my+'px) translate(-50%,-50%)';if(reduce)ring.style.transform=dot.style.transform;});
root.addEventListener('mouseleave',function(){ring.style.opacity='0';dot.style.opacity='0';});root.addEventListener('mouseenter',function(){ring.style.opacity='1';dot.style.opacity='1';});
root.querySelectorAll('.crf-hot').forEach(function(b){b.addEventListener('mouseenter',function(){root.classList.add('is-hot');});b.addEventListener('mouseleave',function(){root.classList.remove('is-hot');});});
if(!reduce){(function loop(){rx+=(mx-rx)*.16;ry+=(my-ry)*.16;ring.style.transform='translate('+rx+'px,'+ry+'px) translate(-50%,-50%)';requestAnimationFrame(loop);})();}
}
init(document.querySelector('.jouw-container'));
Meer uit componenten
Iets gezien dat je mooi vindt?
Zet het in je selectie en stuur hem op. Dan bouwen we je site eromheen, in jouw huisstijl.
Neem contact op →