Product vliegt naar het mandje Nieuw
Klik op "In mandje": het product vliegt in een boog naar het mandje (Web Animations API, keyframes langs een parabool), het mandje tikt en de teller telt op met een aria-live-melding. Werkt in alle browsers; bij reduced motion geen vlucht, alleen de teller. In productie koppel je de klik aan je winkelwagen-API en speel je de vlucht pas af na een geslaagde respons.
Branderij de Maas
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.
<!-- Product vliegt naar het mandje · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="wwv">
<div class="wwv__top"><span class="wwv__logo">Branderij de Maas</span>
<button class="wwv__cart" type="button" aria-label="Winkelmand, 0 artikelen"><svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true"><path d="M3 5h2.2l2.1 10.2a1.5 1.5 0 0 0 1.5 1.2h8.4a1.5 1.5 0 0 0 1.5-1.1L20.5 8H6.2" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/><circle cx="9.5" cy="20" r="1.3" fill="currentColor"/><circle cx="17" cy="20" r="1.3" fill="currentColor"/></svg><span class="wwv__n" aria-hidden="true">0</span></button>
</div>
<div class="wwv__grid">
<div class="wwv__card">
<div class="wwv__img" style="--c:#2b2420"><svg viewBox="0 0 60 70" aria-hidden="true"><path d="M14 10h32l4 10v40a4 4 0 0 1-4 4H14a4 4 0 0 1-4-4V20z" fill="#d8c3a5"/><path d="M14 10h32l4 10H10z" fill="#c2a882"/><rect x="18" y="30" width="24" height="16" rx="1" fill="#0a0a0a"/><path d="M24 38h12" stroke="#F5480F" stroke-width="2"/></svg></div>
<div class="wwv__meta"><b>Huisblend</b><span>250 g · bonen</span><em>€ 8,95</em></div>
<button class="wwv__add" type="button">In mandje</button>
</div>
<div class="wwv__card">
<div class="wwv__img" style="--c:#1d2a26"><svg viewBox="0 0 60 70" aria-hidden="true"><path d="M14 10h32l4 10v40a4 4 0 0 1-4 4H14a4 4 0 0 1-4-4V20z" fill="#6f8f7f"/><path d="M14 10h32l4 10H10z" fill="#5b7a6b"/><rect x="18" y="30" width="24" height="16" rx="1" fill="#f4f3f1"/><path d="M24 38h12" stroke="#0a0a0a" stroke-width="2"/></svg></div>
<div class="wwv__meta"><b>Espresso Feijenoord</b><span>1 kg · bonen</span><em>€ 27,50</em></div>
<button class="wwv__add" type="button">In mandje</button>
</div>
</div>
<p class="wwv__live" aria-live="polite"></p>
</div>
</div>/* Product vliegt naar het mandje · NedDev · eigen werk. */
.wwv{position:absolute;inset:0;display:flex;flex-direction:column;background:#fff;color:#0a0a0a;font-family:'Switzer',system-ui,sans-serif;overflow:hidden}
.wwv__top{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;border-bottom:1px solid #e6e3de}
.wwv__logo{font-weight:800;font-size:13px;letter-spacing:-.01em}
.wwv__cart{appearance:none;position:relative;display:grid;place-items:center;width:36px;height:36px;border:1px solid #d9d6d1;border-radius:999px;background:#fff;color:#0a0a0a;cursor:pointer;transition:border-color .2s}
.wwv__cart:hover{border-color:#0a0a0a}.wwv__cart:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.wwv__n{position:absolute;top:-5px;right:-6px;min-width:18px;height:18px;padding:0 4px;border-radius:9px;background:#F5480F;color:#0a0a0a;font:700 10px/18px 'JetBrains Mono',monospace;text-align:center;font-variant-numeric:tabular-nums;transform:scale(0);transition:transform .25s cubic-bezier(.3,1.6,.5,1)}
.wwv.has-items .wwv__n{transform:scale(1)}
.wwv__grid{flex:1;display:grid;grid-template-columns:1fr 1fr;gap:10px;padding:10px 12px;min-height:0}
.wwv__card{display:grid;grid-template-columns:auto 1fr;grid-template-rows:1fr auto;gap:6px 10px;align-items:center;padding:8px;border:1px solid #e6e3de;border-radius:6px;min-width:0}
.wwv__img{grid-row:1;width:56px;height:68px;display:grid;place-items:center;background:#f4f3f1;border-radius:4px}
.wwv__img svg{width:42px;height:50px}
.wwv__meta{display:flex;flex-direction:column;gap:2px;min-width:0;font-size:12px}
.wwv__meta b{font-size:13px;line-height:1.15}
.wwv__meta span{color:#5f5a54;font-size:11px}
.wwv__meta em{font-style:normal;font:600 12px 'JetBrains Mono',monospace;font-variant-numeric:tabular-nums}
.wwv__add{grid-column:1/-1;appearance:none;border:1px solid #0a0a0a;background:#0a0a0a;color:#fff;font:600 12px 'Switzer',sans-serif;padding:8px 10px;border-radius:4px;cursor:pointer;transition:background-color .16s,color .16s,transform .16s}
.wwv__add:hover{background:#2a2a2a}.wwv__add:active{transform:scale(.975)}
.wwv__add:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.wwv__add.is-done{background:#fff;color:#0a0a0a}
.wwv__add:disabled{cursor:default}
.wwv__fly{position:absolute;z-index:5;pointer-events:none;border-radius:4px;background:#f4f3f1;display:grid;place-items:center;box-shadow:0 6px 16px rgba(0,0,0,.18)}
.wwv__live{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);margin:0}
@media (max-width:420px){.wwv__card{grid-template-columns:1fr;grid-template-rows:auto auto auto;justify-items:start}.wwv__img{width:40px;height:46px}.wwv__img svg{width:30px;height:36px}.wwv__add{width:100%}.wwv__meta b{font-size:12px}}// Product vliegt naar het mandje · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
root=root.querySelector('.wwv')||root;
var cart=root.querySelector('.wwv__cart'),num=root.querySelector('.wwv__n'),live=root.querySelector('.wwv__live'),n=0;
var rm=matchMedia('(prefers-reduced-motion: reduce)').matches;
function bump(name){n++;num.textContent=n;root.classList.add('has-items');cart.setAttribute('aria-label','Winkelmand, '+n+(n===1?' artikel':' artikelen'));live.textContent=name+' toegevoegd aan je winkelmand. Totaal '+n+'.';
if(!rm&&cart.animate){cart.animate([{transform:'rotate(0)'},{transform:'rotate(-14deg) scale(1.08)'},{transform:'rotate(9deg)'},{transform:'rotate(-4deg)'},{transform:'none'}],{duration:480,easing:'ease-out'});num.animate([{transform:'scale(1.5)'},{transform:'scale(1)'}],{duration:300,easing:'cubic-bezier(.3,1.6,.5,1)'});}}
root.querySelectorAll('.wwv__add').forEach(function(btn){
btn.addEventListener('click',function(){
if(btn.disabled)return;var card=btn.closest('.wwv__card'),img=card.querySelector('.wwv__img'),name=card.querySelector('b').textContent;
btn.disabled=true;
var done=function(){bump(name);btn.classList.add('is-done');btn.textContent='Toegevoegd';setTimeout(function(){btn.classList.remove('is-done');btn.textContent='In mandje';btn.disabled=false;},1400);};
if(rm||!img.animate){done();return;}
var R=root.getBoundingClientRect(),a=img.getBoundingClientRect(),b=cart.getBoundingClientRect();
var fly=img.cloneNode(true);fly.className='wwv__fly';fly.style.cssText='left:'+(a.left-R.left)+'px;top:'+(a.top-R.top)+'px;width:'+a.width+'px;height:'+a.height+'px';root.appendChild(fly);
var dx=(b.left+b.width/2)-(a.left+a.width/2),dy=(b.top+b.height/2)-(a.top+a.height/2),lift=Math.max(50,Math.abs(dx)*.35),fr=[];
for(var i=0;i<=16;i++){var t=i/16,x=dx*t,y=dy*t-lift*4*t*(1-t),s=1-.78*t;fr.push({transform:'translate('+x.toFixed(1)+'px,'+y.toFixed(1)+'px) scale('+s.toFixed(3)+') rotate('+(t*-18).toFixed(1)+'deg)',opacity:t>.88?1-(t-.88)*8:1});}
img.animate([{transform:'scale(1)'},{transform:'scale(.9)'},{transform:'scale(1)'}],{duration:300});
fly.animate(fr,{duration:620,easing:'cubic-bezier(.45,.05,.7,.95)'}).onfinish=function(){fly.remove();done();};
});
});
}
init(document.querySelector('.jouw-container'));
Meer uit knoppen
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 →