Slider met vorige/volgende-cursor Nieuw
Projectslider voor een hovenier: met een muis wordt de cursor op de linkerhelft een "Vorige"-knop en rechts een "Volgende"-knop, en klikken bladert. Aan het begin en einde toont de cursor een gedimde staat. Op touch staan er gewone knoppen; toetsenbord werkt met pijltjes, en de knoppen verschijnen bij focus. Teller is aria-live. Alleen (hover: hover) and (pointer: fine) krijgt de cursor.
01 / 04
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.
<!-- Slider met vorige/volgende-cursor · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="slc"><div class="slc__vp" tabindex="0" role="region" aria-roledescription="carrousel" aria-label="Tuinprojecten van Groen en Steen">
<ul class="slc__track">
<li class="slc__slide" aria-roledescription="dia" aria-label="1 van 4"><img src="https://neddev.com/lab-media/slider-cursor-1.webp" alt="Stadstuin met keramische tegels, houten bakken en een meerstammige boom" loading="lazy"><p class="slc__cap"><b>Stadstuin, Leiden</b><span>42 m² · keramische tegels · 2026</span></p></li>
<li class="slc__slide" aria-roledescription="dia" aria-label="2 van 4"><img src="https://neddev.com/lab-media/slider-cursor-2.webp" alt="Voortuin met buxushagen, grindpad en hortensia's bij een jaren-dertighuis" loading="lazy"><p class="slc__cap"><b>Voortuin, Oegstgeest</b><span>jaren-dertigwoning · buxus en grind</span></p></li>
<li class="slc__slide" aria-roledescription="dia" aria-label="3 van 4"><img src="https://neddev.com/lab-media/slider-cursor-3.webp" alt="Daktuin met houten vlonder en plantenbakken boven de stad" loading="lazy"><p class="slc__cap"><b>Daktuin, Rotterdam</b><span>68 m² · vlonder en grassen</span></p></li>
<li class="slc__slide" aria-roledescription="dia" aria-label="4 van 4"><img src="https://neddev.com/lab-media/slider-cursor-4.webp" alt="Tuin met vijver, inheemse planten en een schuur met sedumdak" loading="lazy"><p class="slc__cap"><b>Natuurtuin, Katwijk</b><span>vijver · sedumdak · inheemse planten</span></p></li>
</ul>
<div class="slc__cur" aria-hidden="true"><svg viewBox="0 0 20 20"><path d="M4 10h12M11 5l5 5-5 5"/></svg><span class="slc__cl">Volgende</span></div>
<button class="slc__btn slc__btn--prev" type="button" aria-label="Vorige foto"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M16 10H4M9 5l-5 5 5 5"/></svg></button>
<button class="slc__btn slc__btn--next" type="button" aria-label="Volgende foto"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M4 10h12M11 5l5 5-5 5"/></svg></button>
<p class="slc__tel" aria-live="polite"><span>01</span> / 04</p>
</div></div>
</div>/* Slider met vorige/volgende-cursor · NedDev · eigen werk. */
.slc{position:absolute;inset:0;background:#0a0a0a;font-family:'Switzer',system-ui,sans-serif}
.slc__vp{position:absolute;inset:0;overflow:hidden;outline:none}
.slc__vp:focus-visible{box-shadow:inset 0 0 0 3px #F5480F}
.slc__track{display:flex;height:100%;margin:0;padding:0;list-style:none;transition:transform .55s cubic-bezier(.6,0,.2,1)}
.slc__slide{position:relative;flex:0 0 100%;height:100%}
.slc__slide img{display:block;width:100%;height:100%;object-fit:cover;pointer-events:none;user-select:none}
.slc__cap{position:absolute;left:0;right:0;bottom:0;margin:0;padding:34px 14px 12px;display:flex;flex-direction:column;gap:2px;color:#fff;background:linear-gradient(0deg,rgba(0,0,0,.6),rgba(0,0,0,0))}
.slc__cap b{font:700 15px/1.15 'Switzer',sans-serif}
.slc__cap span{font:500 10px 'JetBrains Mono',monospace;letter-spacing:.03em;opacity:.9}
.slc__tel{position:absolute;right:12px;top:10px;margin:0;font:600 11px 'JetBrains Mono',monospace;color:#fff;background:rgba(10,10,10,.55);padding:4px 7px;border-radius:3px;font-variant-numeric:tabular-nums}
.slc__btn{position:absolute;bottom:12px;width:36px;height:36px;border-radius:50%;border:0;background:#fff;color:#0a0a0a;display:grid;place-items:center;cursor:pointer;transition:background .18s,opacity .18s;z-index:2}
.slc__btn svg,.slc__cur svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.slc__btn--prev{right:54px}.slc__btn--next{right:12px}
.slc__btn:hover{background:#F5480F;color:#fff}
.slc__btn:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.slc__btn[aria-disabled="true"]{opacity:.4;cursor:not-allowed;background:#fff;color:#0a0a0a}
.slc__cur{position:absolute;left:0;top:0;width:76px;height:76px;margin:-38px 0 0 -38px;border-radius:50%;background:#F5480F;color:#fff;display:none;flex-direction:column;align-items:center;justify-content:center;gap:3px;pointer-events:none;z-index:3;transform:translate(-200px,-200px) scale(.4);opacity:0;transition:opacity .18s,background .18s,width .18s,height .18s}
.slc__cur .slc__cl{font:600 10px/1 'JetBrains Mono',monospace;letter-spacing:.04em}
.slc__cur.is-links svg{transform:scaleX(-1)}
.slc__cur.is-uit{background:rgba(255,255,255,.88);color:#555}
.slc__cur.is-uit svg{opacity:.35}
@media (hover:hover) and (pointer:fine){
.slc__vp{cursor:none}
.slc__cur{display:flex}
.slc__vp.is-in .slc__cur{opacity:1}
.slc__btn{opacity:0}
.slc__btn:focus-visible{opacity:1}
}
@media (prefers-reduced-motion: reduce){.slc__track{transition:none}}// Slider met vorige/volgende-cursor · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
root=root.querySelector('.slc')||root;
var vp=root.querySelector('.slc__vp'),tr=root.querySelector('.slc__track'),sl=[].slice.call(root.querySelectorAll('.slc__slide')),cur=root.querySelector('.slc__cur'),cl=root.querySelector('.slc__cl'),tel=root.querySelector('.slc__tel span'),pv=root.querySelector('.slc__btn--prev'),nx=root.querySelector('.slc__btn--next');
var i=0,n=sl.length,rm=matchMedia('(prefers-reduced-motion: reduce)').matches,mx=-200,my=-200,cx=-200,cy=-200,links=false,sc=.4,ts=1,raf=0;
function go(k){if(k<0||k>=n)return;i=k;tr.style.transform='translateX('+(-100*i)+'%)';tel.textContent=('0'+(i+1)).slice(-2);
sl.forEach(function(s,j){s.setAttribute('aria-hidden',j===i?'false':'true');});pv.setAttribute('aria-disabled',i===0?'true':'false');nx.setAttribute('aria-disabled',i===n-1?'true':'false');lab();}
function lab(){var uit=links?i===0:i===n-1;cur.classList.toggle('is-links',links);cur.classList.toggle('is-uit',uit);cl.textContent=uit?(links?'Eerste foto':'Laatste foto'):(links?'Vorige':'Volgende');}
pv.addEventListener('click',function(){go(i-1);});nx.addEventListener('click',function(){go(i+1);});
vp.addEventListener('keydown',function(e){if(e.target!==vp)return;if(e.key==='ArrowLeft'){e.preventDefault();go(i-1);}if(e.key==='ArrowRight'){e.preventDefault();go(i+1);}});
function loop(){var f=rm?1:.22;cx+=(mx-cx)*f;cy+=(my-cy)*f;sc+=(ts-sc)*(rm?1:.25);cur.style.transform='translate('+cx.toFixed(1)+'px,'+cy.toFixed(1)+'px) scale('+sc.toFixed(3)+')';
if(Math.abs(mx-cx)>.3||Math.abs(my-cy)>.3||Math.abs(ts-sc)>.005)raf=requestAnimationFrame(loop);else raf=0;}
function kick(){if(!raf)raf=requestAnimationFrame(loop);}
vp.addEventListener('pointermove',function(e){if(e.pointerType!=='mouse')return;var r=vp.getBoundingClientRect();mx=e.clientX-r.left;my=e.clientY-r.top;
if(!vp.classList.contains('is-in')){cx=mx;cy=my;}vp.classList.add('is-in');var l=mx<r.width/2;if(l!==links){links=l;lab();}
var overKnop=!!e.target.closest('.slc__btn');ts=overKnop?.4:1;kick();});
vp.addEventListener('pointerleave',function(){vp.classList.remove('is-in');ts=.4;kick();});
vp.addEventListener('pointerdown',function(e){if(e.pointerType==='mouse'&&!e.target.closest('.slc__btn')){ts=.88;kick();}});
vp.addEventListener('click',function(e){if(e.target.closest('.slc__btn'))return;if(!matchMedia('(hover:hover) and (pointer:fine)').matches)return;ts=1;kick();go(links?i-1:i+1);});
go(0);
}
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 →


