Zandloper voor een actie New
An hourglass made of real sand grains: they slide past each other, form a heap and run through the narrow neck; turn it over with the button or a click on the glass and the sand runs the other way. Next to it sits the promotion with its end date. For a limited promotion at a garden centre, an early bird rate or the last days of an enrolment. With reduced motion the sand lies still and the button turns it over without animation.
Nog drie dagen bollenweek
20% op alle voorjaarsbollen bij Tuincentrum De Linde in Ede, tot en met zondag 2 november.
How to use it
- Paste the HTML where the components 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.
<!-- 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'));
More components
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 →