Zandloper voor een actie Nieuw
Een zandloper van echte zandkorrels: ze glijden langs elkaar, vormen een bergje en lopen door de smalle hals; draai hem om met de knop of een klik op het glas en het zand loopt de andere kant op. Naast de zandloper staat de actie met de einddatum. Voor een tijdelijke actie van een tuincentrum, een early-bird-tarief of de laatste dagen van een inschrijving. Bij minder beweging ligt het zand stil en draait de knop hem zonder animatie om.
Nog drie dagen bollenweek
20% op alle voorjaarsbollen bij Tuincentrum De Linde in Ede, tot en met zondag 2 november.
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.
<!-- Zandloper voor een actie · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie -->
<div class="jouw-container">
<div class="fyz">
<div class="fyz__glas"><canvas class="fyz__c" aria-hidden="true"></canvas></div>
<div class="fyz__tekst">
<h3 class="fyz__h">Nog drie dagen bollenweek</h3>
<p class="fyz__p">20% op alle voorjaarsbollen bij Tuincentrum De Linde in Ede, tot en met zondag 2 november.</p>
<button class="fyz__knop" type="button">Draai de zandloper om</button>
</div>
</div>
</div>/* Zandloper voor een actie · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie */
.fyz{position:absolute;inset:0;display:flex;align-items:center;gap:16px;padding:12px 18px;background:#f4f3f1;color:#0a0a0a;font-family:'Switzer',sans-serif;text-align:left}
.fyz *{box-sizing:border-box}
.fyz__glas{flex:0 0 auto;cursor:pointer;transition:transform .7s cubic-bezier(.5,-0.2,.3,1.25);will-change:transform}
.fyz__c{display:block}
.fyz__tekst{flex:1;min-width:0;display:flex;flex-direction:column;align-items:flex-start;gap:6px}
.fyz__h{margin:0;font:700 18px/1.15 'Switzer',sans-serif;letter-spacing:-.015em}
.fyz__p{margin:0;font:400 13px/1.4 'Switzer',sans-serif;color:#3d3b37}
.fyz__knop{margin-top:4px;padding:9px 13px;border:0;border-radius:4px;background:#0a0a0a;color:#fff;font:600 13px/1.1 'Switzer',sans-serif;cursor:pointer;transition:background-color .16s,color .16s}
.fyz__knop:hover{background:#F5480F;color:#0a0a0a}
.fyz__knop:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
@media (prefers-reduced-motion: reduce){.fyz__glas{transition:none}}// Zandloper voor een actie · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie
// root = het element waarin de HTML staat
function init(root){
var el=root.querySelector('.fyz');if(!el)return;
var RM=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var glas=el.querySelector('.fyz__glas'),cv=el.querySelector('.fyz__c'),ctx=cv.getContext('2d'),knop=el.querySelector('.fyz__knop');
var GW=45,GH=79,CX=22,MW=20.5,NECK=1.2,cs=3,PAD=8,g=new Uint8Array(GW*GH),raf=0,vis=true,stil=0,draait=false,dir=1,dpr=1,cw=0,ch=0;
function hw(y){var m=(GH-1)/2,u=Math.abs(y-m)/m;return NECK+(MW-NECK)*Math.pow(u,.75);}
function binnen(x,y){return y>=0&&y<GH&&Math.abs(x-CX)<=hw(y)+.01;}
function vul(){g.fill(0);for(var y=3;y<GH/2-2;y++)for(var x=0;x<GW;x++)if(binnen(x,y)&&Math.abs(x-CX)<=hw(y)-.5)g[y*GW+x]=1+((x*7+y*13)%3);
if(RM){for(var y2=GH-1;y2>GH-9;y2--)for(var x2=0;x2<GW;x2++)if(binnen(x2,y2))g[y2*GW+x2]=1+((x2*7+y2*13)%3);for(y=3;y<12;y++)for(x=0;x<GW;x++)g[y*GW+x]=0;}}
function maat(){var r=el.getBoundingClientRect();if(!r.height)return false;cs=Math.max(2,(r.height*.8-2*PAD)/GH);dpr=Math.min(2,window.devicePixelRatio||1);cw=GW*cs+2*PAD;ch=GH*cs+2*PAD;
cv.style.width=cw+'px';cv.style.height=ch+'px';cv.width=Math.round(cw*dpr);cv.height=Math.round(ch*dpr);ctx.setTransform(dpr,0,0,dpr,0,0);return true;}
function teken(){ctx.clearRect(0,0,cw,ch);ctx.save();ctx.translate(PAD,PAD);
ctx.fillStyle='#0a0a0a';ctx.fillRect(-PAD,-PAD,GW*cs+2*PAD,5);ctx.fillRect(-PAD,GH*cs+PAD-5,GW*cs+2*PAD,5);ctx.fillRect(-PAD+1,-PAD,3,GH*cs+2*PAD);ctx.fillRect(GW*cs+PAD-4,-PAD,3,GH*cs+2*PAD);
ctx.beginPath();for(var y=0;y<=GH;y++){var w=hw(Math.min(GH-1,y))+.5;ctx.lineTo((CX+.5-w)*cs,y*cs);}for(y=GH;y>=0;y--){w=hw(Math.min(GH-1,y))+.5;ctx.lineTo((CX+.5+w)*cs,y*cs);}ctx.closePath();
ctx.fillStyle='#ffffff';ctx.fill();ctx.strokeStyle='#0a0a0a';ctx.lineWidth=1.5;ctx.stroke();
var KL=['','#F5480F','#dd3f0b','#ff6a36'];for(y=0;y<GH;y++)for(var x=0;x<GW;x++){var v=g[y*GW+x];if(v){ctx.fillStyle=KL[v];ctx.fillRect(x*cs,y*cs,cs+.25,cs+.25);}}ctx.restore();}
function stap(){var b=0,l2r=Math.random()<.5;for(var y=GH-2;y>=0;y--){for(var i=0;i<GW;i++){var x=l2r?i:GW-1-i,k=y*GW+x;if(!g[k])continue;
var v=g[k];if(binnen(x,y+1)&&!g[k+GW]){g[k]=0;g[k+GW]=v;b++;continue;}var a=Math.random()<.5?-1:1;
for(var q=0;q<2;q++){var nx=x+(q?-a:a);if(binnen(nx,y+1)&&!g[(y+1)*GW+nx]&&binnen(nx,y)){g[k]=0;g[(y+1)*GW+nx]=v;b++;break;}}}}return b;}
function tick(){if(!vis||draait){raf=0;return;}var b=stap();teken();if(!b){if(++stil>30){raf=0;return;}}else stil=0;raf=requestAnimationFrame(tick);}
function kick(){if(RM||raf||draait)return;stil=0;raf=requestAnimationFrame(tick);}
function spiegel(){var n=new Uint8Array(GW*GH);for(var y=0;y<GH;y++)for(var x=0;x<GW;x++)n[(GH-1-y)*GW+x]=g[y*GW+x];g=n;}
function draai(){if(draait)return;if(RM){spiegel();teken();return;}draait=true;glas.style.transform='rotate('+(180*dir)+'deg)';}
glas.addEventListener('transitionend',function(e){if(e.propertyName!=='transform'||!draait)return;spiegel();teken();glas.style.transition='none';glas.style.transform='';void glas.offsetWidth;glas.style.transition='';dir=-dir;draait=false;kick();});
knop.addEventListener('click',draai);glas.addEventListener('click',draai);
if(maat()){vul();teken();kick();}
if('ResizeObserver' in window)new ResizeObserver(function(){var o=cs;if(maat()&&o!==cs)teken();}).observe(el);
if('IntersectionObserver' in window)new IntersectionObserver(function(es){vis=es[0].isIntersecting;if(vis)kick();}).observe(el);
}
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 →