Ballon die opstijgt New
On the thank-you page after an order a balloon hangs on a string with a small weight; let it go (button or click on the balloon) and it rises with buoyancy, sways in the wind and drags its string along. Then the page says when the courier arrives and you can blow up a new balloon. For the thank-you page of a web shop, a birthday promotion or a festive announcement. With reduced motion the balloon disappears at once and the delivery time appears.
Bedankt voor je bestelling
Order 10482 gaat morgen naar Haarlem. Laat de ballon maar los.
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.
<!-- Ballon die opstijgt · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie -->
<div class="jouw-container">
<div class="fyl">
<div class="fyl__tekst">
<h3 class="fyl__h">Bedankt voor je bestelling</h3>
<p class="fyl__p">Order 10482 gaat morgen naar Haarlem. Laat de ballon maar los.</p>
<button class="fyl__knop" type="button">Laat de ballon los</button>
<p class="fyl__code" aria-live="polite"></p>
</div>
<svg class="fyl__touw" aria-hidden="true"><path d=""/></svg>
<span class="fyl__gewicht" aria-hidden="true"></span>
<div class="fyl__ballon" aria-hidden="true"><svg viewBox="0 0 100 124"><path class="fyl__vorm" d="M50 2C79 2 98 25 98 52C98 81 72 104 50 108C28 104 2 81 2 52C2 25 21 2 50 2Z"/><path class="fyl__knoop" d="M43 117L50 106L57 117Z"/><ellipse class="fyl__licht" cx="30" cy="30" rx="9" ry="15" transform="rotate(25 30 30)"/></svg><span class="fyl__t">Bedankt</span></div>
</div>
</div>/* Ballon die opstijgt · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie */
.fyl{position:absolute;inset:0;overflow:hidden;background:#f4f3f1;color:#0a0a0a;font-family:'Switzer',sans-serif;text-align:left}
.fyl *{box-sizing:border-box}
.fyl__tekst{position:absolute;left:16px;top:50%;transform:translateY(-50%);width:54%;display:flex;flex-direction:column;align-items:flex-start;gap:6px;z-index:2}
.fyl__h{margin:0;font:700 18px/1.15 'Switzer',sans-serif;letter-spacing:-.015em}
.fyl__p{margin:0;font:400 13px/1.4 'Switzer',sans-serif;color:#3d3b37}
.fyl__knop{margin-top:2px;padding:9px 13px;border:0;border-radius:4px;background:#0a0a0a;color:#fff;font:600 13px/1 'Switzer',sans-serif;cursor:pointer;transition:background-color .16s,color .16s}
.fyl__knop:hover{background:#F5480F;color:#0a0a0a}
.fyl__knop:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.fyl__code{margin:0;min-height:18px;font:600 13px/1.35 'Switzer',sans-serif}
.fyl__touw{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
.fyl__touw path{fill:none;stroke:#0a0a0a;stroke-width:1.2;stroke-linecap:round}
.fyl__gewicht{position:absolute;left:0;top:0;width:14px;height:10px;border-radius:2px;background:#0a0a0a}
.fyl__ballon{position:absolute;left:0;top:0;width:84px;cursor:pointer;transform-origin:50% 90%;will-change:transform}
.fyl__ballon svg{display:block;width:100%;height:auto}
.fyl__vorm,.fyl__knoop{fill:#F5480F}
.fyl__licht{fill:#fff;opacity:.28}
.fyl__t{position:absolute;left:0;right:0;top:30%;text-align:center;font:800 22px/1 'Switzer',sans-serif;color:#0a0a0a;pointer-events:none}// Ballon die opstijgt · © 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('.fyl');if(!el)return;
var RM=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var bal=el.querySelector('.fyl__ballon'),touw=el.querySelector('.fyl__touw'),pad=touw.querySelector('path'),gew=el.querySelector('.fyl__gewicht'),knop=el.querySelector('.fyl__knop'),code=el.querySelector('.fyl__code'),txt=bal.querySelector('.fyl__t');
var W=1,H=1,bw=84,bh=104,rx=0,ry=0,x=0,y=0,vx=0,vy=0,sc=1,vs=0,modus='vast',N=10,P=[],seg=8,gx=0,gy=0,raf=0,last=0,vis=true,tijd=0,DT=1/60,acc=0;
function maat(){var r=el.getBoundingClientRect();if(!r.width)return false;W=r.width;H=r.height;bw=Math.max(66,Math.min(96,H*.36));bh=bw*1.24;bal.style.width=bw.toFixed(1)+'px';txt.style.fontSize=Math.max(13,bw*.16).toFixed(1)+'px';
touw.setAttribute('viewBox','0 0 '+W.toFixed(1)+' '+H.toFixed(1));rx=W*.77;ry=H*.08;gx=rx-4;gy=H-14;gew.style.transform='translate('+(gx-7).toFixed(1)+'px,'+gy.toFixed(1)+'px)';return true;}
function nieuwTouw(){var kx=x+bw/2,ky=y+bh*.94,L=Math.hypot(gx-kx,gy-ky)+8;seg=L/N;P=[];for(var i=0;i<=N;i++){var u=i/N,px=kx+(gx-kx)*u,py=ky+(gy-ky)*u;P.push({x:px,y:py,px:px,py:py});}}
function teken(){bal.style.transform='translate('+x.toFixed(1)+'px,'+y.toFixed(1)+'px) rotate('+Math.max(-14,Math.min(14,vx*.05)).toFixed(2)+'deg) scale('+sc.toFixed(3)+')';
var d='M'+P[0].x.toFixed(1)+' '+P[0].y.toFixed(1);for(var i=1;i<P.length;i++)d+=' L'+P[i].x.toFixed(1)+' '+P[i].y.toFixed(1);pad.setAttribute('d',d);}
function stap(){tijd+=DT;var i,p;
if(modus==='vast'){var dx=rx+Math.sin(tijd*.9)*W*.025+Math.sin(tijd*2.1)*W*.01-bw/2,dy=ry+Math.sin(tijd*1.4)*4;vx+=((dx-x)*7-vx*2.2)*DT;vy+=((dy-y)*7-vy*2.2)*DT;}
else if(modus==='los'){vy+=-560*DT;vx+=Math.sin(tijd*2.3)*90*DT;vx*=.992;vy*=.996;}
x+=vx*DT;y+=vy*DT;vs+=((1-sc)*260-vs*13)*DT;sc+=vs*DT;
P[0].x=x+bw/2;P[0].y=y+bh*.94*sc+bh*.06;P[0].px=P[0].x;P[0].py=P[0].y;
for(i=1;i<P.length;i++){p=P[i];if(i===N&&modus!=='los'){p.x=gx;p.y=gy;p.px=gx;p.py=gy;continue;}var ux=(p.x-p.px)*.98,uy=(p.y-p.py)*.98;p.px=p.x;p.py=p.y;p.x+=ux;p.y+=uy+380*DT*DT;}
for(var it=0;it<10;it++)for(i=0;i<N;i++){var a=P[i],b=P[i+1],ex=b.x-a.x,ey=b.y-a.y,d=Math.sqrt(ex*ex+ey*ey)||.001;if(d<=seg&&modus!=='los')continue;
var f=(d-seg)/d,wa=i===0?0:.5,wb=(i+1===N&&modus!=='los')?0:.5,s=wa+wb;if(!s)continue;a.x+=ex*f*wa/s;a.y+=ey*f*wa/s;b.x-=ex*f*wb/s;b.y-=ey*f*wb/s;}
if(modus==='los'){if(y+bh<-20&&P[N].y<-10){modus='weg';bal.style.visibility='hidden';pad.setAttribute('d','');toonCode();}}}
function tick(t){if(!vis){raf=0;return;}acc+=Math.min(.05,(t-(tick.l||t))/1000);tick.l=t;while(acc>=DT){stap();acc-=DT;}if(modus!=='weg')teken();raf=modus==='weg'?0:requestAnimationFrame(tick);if(!raf)tick.l=0;}
function kick(){if(RM||raf)return;tick.l=0;acc=0;raf=requestAnimationFrame(tick);}
function toonCode(){code.textContent='Morgen tussen 10:00 en 13:00 staat de bezorger bij je voor de deur.';knop.textContent='Nieuwe ballon';}
function laatLos(){if(modus==='vast'){if(RM){modus='weg';bal.style.visibility='hidden';pad.setAttribute('d','');toonCode();return;}modus='los';vy=-40;knop.textContent='Daar gaat hij';kick();}
else if(modus==='weg'){modus='vast';x=rx-bw/2;y=ry+20;vx=vy=0;bal.style.visibility='';nieuwTouw();knop.textContent='Laat de ballon los';if(RM){sc=1;teken();return;}sc=.25;vs=0;kick();}}
knop.addEventListener('click',laatLos);bal.addEventListener('click',function(){if(modus==='vast')laatLos();});
if(maat()){x=rx-bw/2;y=ry;nieuwTouw();teken();kick();}
if('ResizeObserver' in window)new ResizeObserver(function(){if(maat()&&modus==='vast'){x=rx-bw/2;y=ry;nieuwTouw();teken();}}).observe(el);
if('IntersectionObserver' in window)new IntersectionObserver(function(es){vis=es[0].isIntersecting;if(vis&&modus!=='weg')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 →