Krasbon met kortingscode New
A scratch card like at the market: scratch away the orange area with your mouse or finger and your discount code appears; past halfway the rest falls away by itself and a copy button appears. "Scratch it all open" does it in one go, for keyboard and screen reader users (the code is then announced too). For a promotion page, the thank-you page after a newsletter sign-up or a webshop mailing. Canvas 2D.
Theewinkel Het Blad, Groningen
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.
<!-- Krasbon met kortingscode · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie -->
<div class="jouw-container">
<div class="krb">
<div class="krb__kaart">
<p class="krb__winkel">Theewinkel Het Blad, Groningen</p>
<div class="krb__veld">
<div class="krb__inhoud" aria-hidden="true"><p class="krb__code">Herfst15</p><p class="krb__uitleg">15% korting op je eerste bestelling, tot 30 november</p></div>
<canvas class="krb__cv" aria-hidden="true"></canvas>
</div>
<div class="krb__acties"><button class="krb__open" type="button">Kras alles open</button><button class="krb__kopie" type="button" hidden>Kopieer code</button></div>
<p class="krb__live" aria-live="polite"></p>
</div>
</div>
</div>/* Krasbon met kortingscode · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie */
.krb{position:absolute;inset:0;background:#f4f3f1;display:flex;align-items:center;justify-content:center;padding:12px;box-sizing:border-box;font-family:Switzer,sans-serif;color:#0a0a0a}
.krb__kaart{width:min(360px,100%);background:#fff;border:1px solid rgba(10,10,10,.14);border-radius:8px;padding:12px 14px;box-sizing:border-box}
.krb__winkel{margin:0 0 8px;font:500 13px/1.3 Switzer,sans-serif;color:#4a4a4a}
.krb__veld{position:relative;height:84px;border-radius:4px;overflow:hidden;background:#fdf1ec}
.krb__inhoud{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;padding:0 14px}
.krb__code{margin:0;font:700 28px/1.05 Switzer,sans-serif;letter-spacing:.02em;color:#0a0a0a}
.krb__uitleg{margin:4px 0 0;font:400 13px/1.3 Switzer,sans-serif;color:#3a3a3a}
.krb__cv{position:absolute;inset:0;width:100%;height:100%;display:block;cursor:crosshair;touch-action:none;transition:opacity .45s}
.krb__cv.is-weg{opacity:0;pointer-events:none}
.krb__acties{display:flex;gap:8px;margin-top:10px;min-height:36px}
.krb__open,.krb__kopie{display:inline-flex;align-items:center;min-height:36px;padding:0 14px;border-radius:4px;font:600 14px/1 Switzer,sans-serif;cursor:pointer;transition:background-color .18s,color .18s}
.krb__open{border:1px solid #0a0a0a;background:#fff;color:#0a0a0a}
.krb__kopie{border:0;background:#0a0a0a;color:#fff}
.krb__open:hover,.krb__kopie:hover{background:#F5480F;color:#0a0a0a;border-color:#F5480F}
.krb__open:focus-visible,.krb__kopie:focus-visible{outline:2px solid #F5480F;outline-offset:3px}
.krb__open[hidden],.krb__kopie[hidden]{display:none}
.krb__live{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;margin:0}
@media (prefers-reduced-motion: reduce){.krb__cv,.krb__open,.krb__kopie{transition:none}}// Krasbon met kortingscode · © 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 reduce=!!(window.matchMedia&&matchMedia('(prefers-reduced-motion: reduce)').matches);
function fit(cv,ctx,cb){var dpr=Math.min(window.devicePixelRatio||1,2);function f(){var r=cv.getBoundingClientRect();var w=Math.max(1,Math.round(r.width)),h=Math.max(1,Math.round(r.height));if(cv.width===Math.round(w*dpr)&&cv.height===Math.round(h*dpr))return;cv.width=Math.round(w*dpr);cv.height=Math.round(h*dpr);if(ctx)ctx.setTransform(dpr,0,0,dpr,0,0);if(cb)cb(w,h,dpr);}if(window.ResizeObserver)new ResizeObserver(f).observe(cv);f();}
function loop(el,step){var on=false,raf=0,last=0;function fr(t){raf=requestAnimationFrame(fr);var dt=last?Math.min(.05,(t-last)/1000):.016;last=t;step(dt,t/1000);}function go(v){if(v&&!on){on=true;last=0;raf=requestAnimationFrame(fr);}else if(!v&&on){on=false;cancelAnimationFrame(raf);}}if(window.IntersectionObserver)new IntersectionObserver(function(es){go(es[0].isIntersecting);}).observe(el);else go(true);}
var w = root.querySelector('.krb'), cv = w.querySelector('.krb__cv'), ctx = cv.getContext('2d', { willReadFrequently: true }), inh = w.querySelector('.krb__inhoud');
var bOpen = w.querySelector('.krb__open'), bKop = w.querySelector('.krb__kopie'), live = w.querySelector('.krb__live');
var W = 1, H = 1, dpr = 1, down = false, lx = 0, ly = 0, moves = 0, done = false;
function cover() {
ctx.globalCompositeOperation = 'source-over';
ctx.fillStyle = '#F5480F'; ctx.fillRect(0, 0, W, H);
ctx.strokeStyle = 'rgba(255,255,255,.14)'; ctx.lineWidth = 6;
for (var x = -H; x < W; x += 18) { ctx.beginPath(); ctx.moveTo(x, H); ctx.lineTo(x + H, 0); ctx.stroke(); }
ctx.fillStyle = '#0a0a0a'; ctx.font = '600 15px Switzer, sans-serif'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle';
ctx.fillText('Kras hier met je muis of vinger', W / 2, H / 2);
}
fit(cv, ctx, function (a, b, d) { W = a; H = b; dpr = d; if (!done) cover(); });
(document.fonts && document.fonts.ready ? document.fonts.ready : Promise.resolve()).then(function () { if (!done) cover(); });
function reveal() {
if (done) return; done = true;
cv.classList.add('is-weg'); inh.removeAttribute('aria-hidden');
bOpen.hidden = true; bKop.hidden = false;
live.textContent = 'Je kortingscode is Herfst15: 15% korting op je eerste bestelling, tot 30 november.';
if (document.activeElement === bOpen || !document.activeElement || document.activeElement === document.body) bKop.focus({ preventScroll: true });
}
function check() {
var d = ctx.getImageData(0, 0, cv.width, cv.height).data, step = 10, tot = 0, gone = 0;
for (var i = 3; i < d.length; i += 4 * step) { tot++; if (d[i] < 40) gone++; }
if (gone / tot > .5) reveal();
}
function scratch(x, y) {
ctx.globalCompositeOperation = 'destination-out'; ctx.strokeStyle = '#000'; ctx.lineCap = 'round'; ctx.lineJoin = 'round'; ctx.lineWidth = 28;
ctx.beginPath(); ctx.moveTo(lx, ly); ctx.lineTo(x + .01, y); ctx.stroke(); lx = x; ly = y;
if (++moves % 8 === 0) check();
}
function pos(e) { var r = cv.getBoundingClientRect(); return [e.clientX - r.left, e.clientY - r.top]; }
cv.addEventListener('pointerdown', function (e) { if (done) return; down = true; try { cv.setPointerCapture(e.pointerId); } catch (_) {} var p = pos(e); lx = p[0]; ly = p[1]; scratch(p[0], p[1]); });
cv.addEventListener('pointermove', function (e) { if (!down || done) return; var p = pos(e); scratch(p[0], p[1]); });
cv.addEventListener('pointerup', function () { down = false; if (!done) check(); });
cv.addEventListener('pointercancel', function () { down = false; });
bOpen.addEventListener('click', reveal);
bKop.addEventListener('click', function () {
try { if (navigator.clipboard) navigator.clipboard.writeText('Herfst15'); } catch (_) {}
bKop.textContent = 'Gekopieerd'; live.textContent = 'Code Herfst15 gekopieerd.';
setTimeout(function () { bKop.textContent = 'Kopieer code'; }, 1600);
});
}
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 →