Zijlade: mini-winkelwagen Nieuw
Off-canvas lade van rechts als mini-winkelwagen: aantallen aanpassen, verwijderen, teller tot gratis verzending, lege staat en een afrekenknop met laadstaat. Gebouwd op
Branderij De Molen
- Huisblend500 g · bonen€ 12,95
- Espresso Utrecht1 kg · bonen€ 24,50
- Decaf Colombia250 g · gemalen€ 8,75
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.
<!-- Zijlade: mini-winkelwagen · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="drr">
<div class="drr__shop">
<div class="drr__top"><span class="drr__logo">Branderij De Molen</span><button class="drr__cartbtn" type="button" aria-haspopup="dialog">Winkelwagen <span class="drr__badge" aria-label="artikelen">2</span></button></div>
<ul class="drr__prods">
<li class="drr__prod"><span class="drr__pack drr__pack--a" aria-hidden="true"></span><span class="drr__pi"><strong>Huisblend</strong><span>500 g · bonen</span></span><b>€ 12,95</b><button class="drr__add" type="button" data-id="huis">Toevoegen</button></li>
<li class="drr__prod"><span class="drr__pack drr__pack--b" aria-hidden="true"></span><span class="drr__pi"><strong>Espresso Utrecht</strong><span>1 kg · bonen</span></span><b>€ 24,50</b><button class="drr__add" type="button" data-id="esp">Toevoegen</button></li>
<li class="drr__prod"><span class="drr__pack drr__pack--c" aria-hidden="true"></span><span class="drr__pi"><strong>Decaf Colombia</strong><span>250 g · gemalen</span></span><b>€ 8,75</b><button class="drr__add" type="button" data-id="dec">Toevoegen</button></li>
</ul>
</div>
<div class="drr__scrim"></div>
<dialog class="drr__panel" aria-labelledby="drr-h">
<div class="drr__head"><h3 id="drr-h" class="drr__h">Winkelwagen <span class="drr__n"></span></h3><button class="drr__x" type="button" aria-label="Sluit winkelwagen"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6 6l12 12M18 6 6 18"/></svg></button></div>
<div class="drr__ship"><p class="drr__shiptxt"></p><span class="drr__shipbar"><span></span></span></div>
<ul class="drr__list"></ul>
<div class="drr__empty"><p>Je winkelwagen is leeg.</p><button class="drr__ghost drr__close2" type="button">Bekijk de koffie</button></div>
<div class="drr__foot"><div class="drr__sub"><span>Subtotaal</span><b class="drr__subv"></b></div><button class="drr__pay" type="button">Afrekenen met iDEAL</button><button class="drr__ghost drr__close2" type="button">Verder winkelen</button></div>
</dialog>
<p class="drr__sr" aria-live="polite"></p>
</div>
</div>/* Zijlade: mini-winkelwagen · NedDev · eigen werk. */
.drr{--ink:#0a0a0a;--pop:#F5480F;--pd:#b83a0b;--line:rgba(10,10,10,.12);position:absolute;inset:0;overflow:hidden;font-family:'Switzer',system-ui,sans-serif;color:var(--ink);background:#f4f3f1}
.drr__shop{height:100%;display:flex;flex-direction:column}
.drr__top{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:9px 12px;border-bottom:1px solid var(--line);background:#fff}
.drr__logo{font-weight:700;font-size:14px;letter-spacing:-.01em}
.drr__cartbtn{display:inline-flex;gap:8px;align-items:center;font:600 12px/1 'Switzer',system-ui,sans-serif;padding:6px 6px 6px 12px;border:1px solid var(--ink);border-radius:100px;background:#fff;color:var(--ink);cursor:pointer;transition:background .15s,color .15s}
.drr__cartbtn:hover{background:var(--ink);color:#fff}
.drr__badge{min-width:22px;height:22px;padding:0 6px;border-radius:11px;background:var(--pop);color:var(--ink);font:700 11px/22px 'JetBrains Mono',monospace;text-align:center}
.drr__badge.is-bump{animation:drr-bump .35s ease}
@keyframes drr-bump{40%{transform:scale(1.3)}}
.drr__prods{list-style:none;margin:0;padding:6px 12px;flex:1;overflow:auto}
.drr__prod{display:flex;align-items:center;gap:10px;padding:7px 0;border-bottom:1px solid var(--line);font-size:12.5px}
.drr__prod:last-child{border-bottom:0}
.drr__pack{width:26px;height:34px;border-radius:3px 3px 2px 2px;flex:none;position:relative}
.drr__pack::after{content:'';position:absolute;left:4px;right:4px;top:12px;height:8px;background:#fff;border-radius:1px}
.drr__pack--a{background:#2b211b}.drr__pack--b{background:var(--pop)}.drr__pack--c{background:#8b9a6b}
.drr__pi{flex:1;min-width:0;display:flex;flex-direction:column}
.drr__pi strong{font-size:13px}
.drr__pi span{color:#5b5b5b;font-size:11.5px}
.drr__prod b{font-variant-numeric:tabular-nums;font-weight:600;white-space:nowrap}
.drr__add{font:600 11.5px/1 'Switzer',system-ui,sans-serif;padding:8px 10px;border-radius:4px;border:1px solid var(--ink);background:#fff;color:var(--ink);cursor:pointer;transition:background .15s,color .15s}
.drr__add:hover{background:var(--ink);color:#fff}
.drr__add:active{transform:translateY(1px)}
.drr button:focus-visible{outline:2px solid var(--pd);outline-offset:2px}
.drr__scrim{position:absolute;inset:0;background:rgba(10,10,10,.45);opacity:0;pointer-events:none;transition:opacity .25s}
.drr.is-open .drr__scrim{opacity:1;pointer-events:auto}
.drr__panel{position:absolute;top:0;bottom:0;left:auto;right:0;margin:0;width:min(290px,88%);height:100%;max-width:none;max-height:none;border:0;padding:0;background:#fff;color:var(--ink);display:flex;flex-direction:column;transform:translateX(100%);box-shadow:-12px 0 32px rgba(0,0,0,.18);transition:transform .3s cubic-bezier(.2,.8,.2,1),display .3s allow-discrete,overlay .3s allow-discrete}
.drr__panel:not([open]){display:none}
.drr__panel[open]{transform:none}
@starting-style{.drr__panel[open]{transform:translateX(100%)}}
.drr__head{display:flex;align-items:center;justify-content:space-between;padding:8px 8px 8px 14px;border-bottom:1px solid var(--line)}
.drr__h{margin:0;font-size:14px;font-weight:700}
.drr__n{font-weight:500;color:#5b5b5b}
.drr__x{width:32px;height:32px;border:0;border-radius:4px;background:none;cursor:pointer;display:grid;place-items:center;color:var(--ink)}
.drr__x:hover{background:#f0eeea}
.drr__x svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}
.drr__ship{padding:7px 14px;background:#f4f3f1}
.drr__shiptxt{margin:0 0 5px;font-size:11.5px}
.drr__shipbar{display:block;height:4px;border-radius:2px;background:#e1ded8;overflow:hidden}
.drr__shipbar span{display:block;height:100%;width:0;background:var(--ink);transition:width .35s ease}
.drr__shipbar.is-free span{background:#16833f}
.drr__list{list-style:none;margin:0;padding:0 14px;flex:1;min-height:0;overflow:auto}
.drr__row{display:flex;align-items:center;gap:8px;padding:8px 0;border-bottom:1px solid var(--line);font-size:12.5px}
.drr__rn{flex:1;min-width:0;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.drr__rn small{display:block;font-weight:400;color:#5b5b5b;font-variant-numeric:tabular-nums}
.drr__qty{display:flex;align-items:center;border:1px solid var(--line);border-radius:4px}
.drr__qty button{width:24px;height:24px;border:0;background:none;cursor:pointer;font:600 14px/1 system-ui,sans-serif;color:var(--ink)}
.drr__qty button:hover{background:#f0eeea}
.drr__qty span{min-width:18px;text-align:center;font:600 12px/1 'JetBrains Mono',monospace}
.drr__rp{font-variant-numeric:tabular-nums;font-weight:600;min-width:52px;text-align:right}
.drr__del{border:0;background:none;padding:4px;cursor:pointer;color:#5b5b5b;font-size:11px;text-decoration:underline}
.drr__del:hover{color:var(--ink)}
.drr__empty{display:none;flex:1;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:14px;text-align:center;font-size:13px}
.drr__empty p{margin:0;color:#5b5b5b}
.drr.is-empty .drr__empty{display:flex}.drr.is-empty .drr__list,.drr.is-empty .drr__foot{display:none}
.drr__foot{padding:8px 14px 10px;border-top:1px solid var(--line);display:grid;gap:6px}
.drr__sub{display:flex;justify-content:space-between;font-size:13px}
.drr__sub b{font-variant-numeric:tabular-nums}
.drr__pay{display:flex;align-items:center;justify-content:center;gap:8px;padding:9px;border:0;border-radius:4px;background:var(--pop);color:var(--ink);font:700 12.5px/1 'Switzer',system-ui,sans-serif;cursor:pointer;transition:background .15s}
.drr__pay:hover{background:#ff6a35}
.drr__pay[aria-busy=true]{background:#f7a07f;cursor:progress}
.drr__pay[aria-busy=true]::before{content:'';width:12px;height:12px;border:2px solid var(--ink);border-right-color:transparent;border-radius:50%;animation:drr-spin .7s linear infinite}
.drr__pay.is-done{background:#16833f;color:#fff}
@keyframes drr-spin{to{transform:rotate(360deg)}}
.drr__ghost{padding:6px;border:0;background:none;color:var(--ink);font:500 12px/1 'Switzer',system-ui,sans-serif;text-decoration:underline;text-underline-offset:3px;cursor:pointer}
.drr__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;margin:0}
@media (max-height:230px),(max-width:400px){.drr__ship{padding:5px 14px}.drr__row{padding:5px 0}.drr__foot{gap:3px;padding:6px 14px 6px}.drr__foot .drr__ghost{display:none}.drr__prod{padding:5px 0}}
@media (prefers-reduced-motion:reduce){.drr__panel,.drr__scrim,.drr__shipbar span{transition:none}.drr__badge.is-bump{animation:none}}// Zijlade: mini-winkelwagen · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
var w=root.querySelector('.drr');if(!w)return;
var U='-'+Math.random().toString(36).slice(2,7),h=w.querySelector('.drr__h');h.id=h.id+U;
var dlg=w.querySelector('.drr__panel');dlg.setAttribute('aria-labelledby',h.id);
var shop=w.querySelector('.drr__shop'),scrim=w.querySelector('.drr__scrim'),list=w.querySelector('.drr__list'),badge=w.querySelector('.drr__badge'),pay=w.querySelector('.drr__pay'),sr=w.querySelector('.drr__sr');
var P={huis:{n:'Huisblend',m:'500 g',p:1295},esp:{n:'Espresso Utrecht',m:'1 kg',p:2450},dec:{n:'Decaf Colombia',m:'250 g',p:875}};
var cart={huis:1,esp:1},FREE=4000,opener=null;
function eur(c){var s=(c/100).toFixed(2).split('.');return '€ '+s[0].replace(/(?=(?:[0-9]{3})+$)(?!^)/g,'.')+','+s[1];}
function render(){var keys=Object.keys(cart).filter(function(k){return cart[k]>0;}),n=0,sum=0;list.innerHTML='';
keys.forEach(function(k){var q=cart[k],it=P[k];n+=q;sum+=q*it.p;var li=document.createElement('li');li.className='drr__row';
li.innerHTML='<span class="drr__rn">'+it.n+'<small>'+it.m+' · '+eur(it.p)+'</small></span><span class="drr__qty"><button type="button" data-d="-1" aria-label="Eén minder '+it.n+'">−</button><span aria-label="Aantal">'+q+'</span><button type="button" data-d="1" aria-label="Eén meer '+it.n+'">+</button></span><span class="drr__rp">'+eur(q*it.p)+'</span><button class="drr__del" type="button" aria-label="Verwijder '+it.n+'">Wis</button>';
li.querySelectorAll('[data-d]').forEach(function(b){b.addEventListener('click',function(){cart[k]=Math.max(0,q+ +b.dataset.d);render();var nb=list.querySelector('[aria-label="'+b.getAttribute('aria-label')+'"]');(nb||w.querySelector('.drr__x')).focus();sr.textContent=it.n+': '+(cart[k]||0)+' stuks';});});
li.querySelector('.drr__del').addEventListener('click',function(){delete cart[k];render();w.querySelector('.drr__x').focus();sr.textContent=it.n+' verwijderd';});
list.appendChild(li);});
badge.textContent=n;w.querySelector('.drr__n').textContent='('+n+')';w.querySelector('.drr__subv').textContent=eur(sum);
var rest=FREE-sum,bar=w.querySelector('.drr__shipbar');w.querySelector('.drr__shiptxt').innerHTML=rest>0?'Nog <b>'+eur(rest)+'</b> tot gratis verzending':'<b>Gratis verzending</b> binnen Nederland';
bar.classList.toggle('is-free',rest<=0);bar.firstElementChild.style.width=Math.min(100,sum/FREE*100)+'%';w.classList.toggle('is-empty',n===0);}
function focusables(){return [].slice.call(dlg.querySelectorAll('button,a[href],input,select')).filter(function(e){return e.offsetParent!==null&&!e.disabled;});}
function open(from){opener=from;if(dlg.open)return;dlg.show();w.classList.add('is-open');shop.inert=true;setTimeout(function(){w.querySelector('.drr__x').focus();},30);}
function close(){if(!dlg.open)return;w.classList.remove('is-open');dlg.close();shop.inert=false;if(opener)opener.focus();}
w.querySelector('.drr__cartbtn').addEventListener('click',function(e){open(e.currentTarget);});
w.querySelectorAll('.drr__add').forEach(function(b){b.addEventListener('click',function(){var k=b.dataset.id;cart[k]=(cart[k]||0)+1;render();badge.classList.remove('is-bump');void badge.offsetWidth;badge.classList.add('is-bump');sr.textContent=P[k].n+' toegevoegd';open(b);});});
w.querySelector('.drr__x').addEventListener('click',close);scrim.addEventListener('click',close);
w.querySelectorAll('.drr__close2').forEach(function(b){b.addEventListener('click',close);});
dlg.addEventListener('keydown',function(e){if(e.key==='Escape'){e.preventDefault();close();return;}
if(e.key==='Tab'){var f=focusables();if(!f.length)return;var a=f[0],z=f[f.length-1];if(e.shiftKey&&document.activeElement===a){e.preventDefault();z.focus();}else if(!e.shiftKey&&document.activeElement===z){e.preventDefault();a.focus();}}});
dlg.addEventListener('cancel',function(e){e.preventDefault();close();});
pay.addEventListener('click',function(){if(pay.getAttribute('aria-busy')==='true')return;pay.setAttribute('aria-busy','true');pay.textContent='Even geduld';
setTimeout(function(){pay.removeAttribute('aria-busy');pay.classList.add('is-done');pay.textContent='Doorsturen naar iDEAL';sr.textContent='Je wordt doorgestuurd naar iDEAL';
setTimeout(function(){pay.classList.remove('is-done');pay.textContent='Afrekenen met iDEAL';},1800);},1000);});
render();
}
init(document.querySelector('.jouw-container'));
Meer uit navigatie & menu's
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 →