3D-verpakking draaien Nieuw
Een verpakking als echt 3D-blok in CSS (zes vlakken, preserve-3d) dat je met muis of vinger draait, met uitloop en licht dat per vlak meerekent. Knoppen springen naar voorkant, zijkant en achterkant; pijltjestoetsen draaien per 15 graden. Geen WebGL of 3D-bestand nodig: voor koffie, thee, cosmetica en andere doosvormige producten in een webshop.
Ethiopië Yirgacheffe
Hele bonen, 250 g
€ 12,90
Zo gebruik je het
- Plak de HTML op de plek waar het onderdeel moet komen. Zet de script-tags bovenaan één keer per pagina.
- 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.
<!-- 3D-verpakking draaien · NedDev · eigen werk. -->
<!-- benodigd, één keer per pagina: -->
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/gsap.min.js"></script>
<div class="jouw-container">
<div class="p3d"><div class="p3d__in">
<div class="p3d__info">
<b class="p3d__ti">Ethiopië Yirgacheffe</b>
<span class="p3d__me">Hele bonen, 250 g</span>
<span class="p3d__pr">€ 12,90</span>
<div class="p3d__btns" role="group" aria-label="Kant van de verpakking">
<button class="p3d__btn" type="button" data-r="0" aria-pressed="true">Voorkant</button>
<button class="p3d__btn" type="button" data-r="-90" aria-pressed="false">Zijkant</button>
<button class="p3d__btn" type="button" data-r="180" aria-pressed="false">Achterkant</button>
</div>
</div>
<div class="p3d__scene" tabindex="0" role="img" aria-label="3D-weergave van de koffieverpakking. Sleep of gebruik de pijltjestoetsen om te draaien.">
<div class="p3d__shadow" aria-hidden="true"></div>
<div class="p3d__box" aria-hidden="true">
<div class="p3d__f p3d__f--front"><span class="p3d__brand">Dok</span><span class="p3d__origin">Ethiopië<br>Yirgacheffe</span><span class="p3d__w">250 g · bonen</span><i class="p3d__sh"></i></div>
<div class="p3d__f p3d__f--back"><span class="p3d__bt">Bergamot, perzik en honing</span><span class="p3d__bs">Gebrand 6 okt 2026 in Rotterdam</span><i class="p3d__sh"></i></div>
<div class="p3d__f p3d__f--right"><span class="p3d__side">Dok koffiebranders</span><i class="p3d__sh"></i></div>
<div class="p3d__f p3d__f--left"><span class="p3d__side">Licht gebrand</span><i class="p3d__sh"></i></div>
<div class="p3d__f p3d__f--top"><span class="p3d__valve"></span><i class="p3d__sh"></i></div>
<div class="p3d__f p3d__f--bottom"><i class="p3d__sh"></i></div>
</div>
</div>
</div></div>
</div>/* 3D-verpakking draaien · NedDev · eigen werk. */
.p3d{position:absolute;inset:0;background:#f4f3f1;color:#0a0a0a;font-family:'Switzer',sans-serif;text-align:left;container-type:inline-size}
.p3d__in{--W:104px;--H:150px;--D:62px;position:absolute;inset:0;display:grid;grid-template-columns:150px 1fr}
.p3d__info{display:flex;flex-direction:column;justify-content:center;gap:6px;padding:16px 0 16px 16px}
.p3d__ti{font:600 16px/1.2 'Switzer',sans-serif;letter-spacing:-.01em}
.p3d__me{font:400 13px/1.4 'Switzer',sans-serif;color:#55524d}
.p3d__pr{font:600 14px/1.2 'Switzer',sans-serif;font-variant-numeric:tabular-nums}
.p3d__btns{display:flex;flex-direction:column;align-items:flex-start;gap:4px;margin-top:8px}
.p3d__btn{min-height:28px;padding:0 10px;border:1.5px solid transparent;border-radius:4px;background:transparent;color:#0a0a0a;font:500 13px/1 'Switzer',sans-serif;cursor:pointer}
.p3d__btn:hover{border-color:#0a0a0a}
.p3d__btn[aria-pressed="true"]{background:#0a0a0a;color:#fff}
.p3d__btn:focus-visible,.p3d__scene:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.p3d__scene{position:relative;perspective:700px;display:grid;place-items:center;cursor:grab;touch-action:pan-y;user-select:none;-webkit-user-select:none;outline:none}
.p3d__scene:active{cursor:grabbing}
.p3d__shadow{position:absolute;left:50%;top:50%;width:150px;height:30px;margin:72px 0 0 -75px;border-radius:50%;background:radial-gradient(closest-side,rgba(10,10,10,.22),rgba(10,10,10,0))}
.p3d__box{position:relative;width:var(--W);height:var(--H);transform-style:preserve-3d;transform:rotateX(var(--rx,-12deg)) rotateY(var(--ry,-28deg))}
.p3d__f{position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden;backface-visibility:hidden}
.p3d__sh{position:absolute;inset:0;background:#0a0a0a;opacity:var(--s,0);pointer-events:none}
.p3d__f--front,.p3d__f--back{width:var(--W);height:var(--H)}
.p3d__f--front{transform:translateZ(calc(var(--D) / 2));background:#F5480F;color:#0a0a0a;padding:12px 10px;display:flex;flex-direction:column}
.p3d__f--back{transform:rotateY(180deg) translateZ(calc(var(--D) / 2));background:#fff;padding:12px 10px;display:flex;flex-direction:column;justify-content:space-between}
.p3d__f--right,.p3d__f--left{width:var(--D);height:var(--H);left:calc((var(--W) - var(--D)) / 2);background:#0a0a0a;color:#fff;display:grid;place-items:center}
.p3d__f--right{transform:rotateY(90deg) translateZ(calc(var(--W) / 2))}
.p3d__f--left{transform:rotateY(-90deg) translateZ(calc(var(--W) / 2))}
.p3d__f--top,.p3d__f--bottom{width:var(--W);height:var(--D);top:calc((var(--H) - var(--D)) / 2);background:#1c1b1a}
.p3d__f--top{transform:rotateX(90deg) translateZ(calc(var(--H) / 2));display:grid;place-items:center}
.p3d__f--bottom{transform:rotateX(-90deg) translateZ(calc(var(--H) / 2));background:#e6e3de}
.p3d__brand{font:800 26px/1 'Switzer',sans-serif;letter-spacing:-.03em}
.p3d__origin{margin-top:auto;font:600 13px/1.2 'Switzer',sans-serif}
.p3d__w{margin-top:6px;padding-top:6px;border-top:1.5px solid #0a0a0a;font:500 12px/1.2 'Switzer',sans-serif}
.p3d__bt{font:600 13px/1.3 'Switzer',sans-serif}
.p3d__bs{font:400 12px/1.3 'Switzer',sans-serif;color:#55524d}
.p3d__side{transform:rotate(-90deg);white-space:nowrap;font:600 12px/1 'Switzer',sans-serif}
.p3d__valve{width:16px;height:16px;border-radius:50%;border:2px solid #5c5a57}
@container (max-width:370px){.p3d__in{grid-template-columns:128px 1fr;--W:92px;--H:132px;--D:56px}.p3d__info{padding-left:12px}.p3d__ti{font-size:15px}.p3d__shadow{margin-top:62px}}// 3D-verpakking draaien · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
var w=root.querySelector('.p3d');if(!w)return;
var sc=w.querySelector('.p3d__scene'),box=w.querySelector('.p3d__box'),btns=[].slice.call(w.querySelectorAll('.p3d__btn'));
var rm=matchMedia('(prefers-reduced-motion: reduce)').matches;
var rx=-12,ry=-28,vx=0,vy=0,drag=false,lx=0,ly=0,raf=0,tw=null;
var faces={front:[0,0,1],back:[0,0,-1],right:[1,0,0],left:[-1,0,0],top:[0,1,0],bottom:[0,-1,0]},els={};
Object.keys(faces).forEach(function(k){els[k]=w.querySelector('.p3d__f--'+k+' .p3d__sh');});
var L=[-.45,.55,.7],l=Math.hypot(L[0],L[1],L[2]);L=[L[0]/l,L[1]/l,L[2]/l];
function shade(){var a=rx*Math.PI/180,b=ry*Math.PI/180,ca=Math.cos(a),sa=Math.sin(a),cb=Math.cos(b),sb=Math.sin(b);
Object.keys(faces).forEach(function(k){var n=faces[k];
/* rotateY(b) dan rotateX(a); CSS y-as wijst omlaag, dus top = +y in wereld */
var x1=n[0]*cb+n[2]*sb,z1=-n[0]*sb+n[2]*cb,y1=n[1];var y2=y1*ca+z1*sa,z2=-y1*sa+z1*ca;
var d=Math.max(0,x1*L[0]+y2*L[1]+z2*L[2]);els[k].style.setProperty('--s',(0.42-0.42*d).toFixed(3));});}
function apply(){rx=Math.max(-60,Math.min(60,rx));box.style.setProperty('--rx',rx+'deg');box.style.setProperty('--ry',ry+'deg');shade();
var a=((ry%360)+360)%360,act=(a<45||a>315)?0:(a>135&&a<225)?2:(a>=225&&a<=315)?1:-1;btns.forEach(function(b,i){b.setAttribute('aria-pressed',i===act?'true':'false');});}
function loop(){raf=0;if(drag)return;if(Math.abs(vx)+Math.abs(vy)<.05)return;ry+=vy;rx+=vx;vx*=.92;vy*=.92;apply();raf=requestAnimationFrame(loop);}
function to(tx,ty){cancelAnimationFrame(raf);raf=0;vx=vy=0;var d=((ty-ry)%360+540)%360-180;ty=ry+d;
if(rm||!window.gsap){rx=tx;ry=ty;apply();return;}if(tw)tw.kill();var o={x:rx,y:ry};tw=gsap.to(o,{x:tx,y:ty,duration:.7,ease:'power3.out',onUpdate:function(){rx=o.x;ry=o.y;apply();}});}
sc.addEventListener('pointerdown',function(e){drag=true;if(tw)tw.kill();lx=e.clientX;ly=e.clientY;vx=vy=0;try{sc.setPointerCapture(e.pointerId);}catch(_){}});
sc.addEventListener('pointermove',function(e){if(!drag)return;var dx=e.clientX-lx,dy=e.clientY-ly;lx=e.clientX;ly=e.clientY;ry+=dx*.6;rx-=dy*.6;vy=rm?0:dx*.6;vx=rm?0:-dy*.6;apply();});
function up(){if(!drag)return;drag=false;if(!raf)raf=requestAnimationFrame(loop);}
sc.addEventListener('pointerup',up);sc.addEventListener('pointercancel',up);
sc.addEventListener('keydown',function(e){var k=e.key;if(k==='ArrowLeft')ry-=15;else if(k==='ArrowRight')ry+=15;else if(k==='ArrowUp')rx+=15;else if(k==='ArrowDown')rx-=15;else return;e.preventDefault();if(tw)tw.kill();apply();});
btns.forEach(function(b){b.addEventListener('click',function(){to(-12,+b.dataset.r);});});
apply();
}
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 →