404 van deeltjes die uiteenvallen New
A 404 page where the number is made of hundreds of small blocks: they fly into place on arrival, move away from your mouse or finger and fall apart on a click, then gather again. Turns a dead end into something to play with, with the way back right next to it. Also works with your own wordmark or a single word ("Welcome", "Thank you"). Canvas 2D; with reduced motion the number stays still.
404. Deze pagina is uit elkaar gevallen.
How to use it
- Paste the HTML where the backgrounds & webgl 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.
<!-- 404 van deeltjes die uiteenvallen · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie -->
<div class="jouw-container">
<div class="dpw">
<canvas class="dpw__cv" aria-hidden="true"></canvas>
<div class="dpw__txt">
<p class="dpw__h"><span class="dpw__sr">404. </span>Deze pagina is uit elkaar gevallen.</p>
<div class="dpw__acties"><a class="dpw__link" href="#">Terug naar de homepage</a><button class="dpw__btn" type="button">Opnieuw</button></div>
</div>
</div>
</div>/* 404 van deeltjes die uiteenvallen · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie */
.dpw{position:absolute;inset:0;background:#f4f3f1;font-family:Switzer,sans-serif;color:#0a0a0a;overflow:hidden}
.dpw__cv{position:absolute;inset:0;width:100%;height:100%;display:block;touch-action:pan-y}
.dpw__txt{position:absolute;left:16px;right:16px;bottom:14px;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 16px}
.dpw__h{margin:0;font:500 15px/1.3 Switzer,sans-serif}
.dpw__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.dpw__acties{display:flex;gap:8px}
.dpw__link{display:inline-flex;align-items:center;min-height:36px;padding:0 12px;border-radius:4px;background:#0a0a0a;color:#fff;font:600 14px/1 Switzer,sans-serif;text-decoration:none;transition:background-color .18s,color .18s}
.dpw__link:hover{background:#F5480F;color:#0a0a0a}.dpw__link:focus-visible{outline:2px solid #F5480F;outline-offset:3px}
.dpw__btn{display:inline-flex;align-items:center;min-height:36px;padding:0 12px;border:1px solid #0a0a0a;border-radius:4px;background:transparent;color:#0a0a0a;font:500 14px/1 Switzer,sans-serif;cursor:pointer}
.dpw__btn:hover{border-color:#F5480F;color:#0a0a0a}.dpw__btn:focus-visible{outline:2px solid #F5480F;outline-offset:3px}
@media (prefers-reduced-motion: reduce){.dpw__link{transition:none}}// 404 van deeltjes die uiteenvallen · © 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('.dpw'), cv = w.querySelector('.dpw__cv'), ctx = cv.getContext('2d');
var W = 1, H = 1, ps = [], sz = 3, mx = -999, my = -999, ready = false, loose = 0;
function build() {
var off = document.createElement('canvas'); off.width = W; off.height = H; var o = off.getContext('2d');
var fs = Math.min(H * .48, W * .34);
o.font = '800 ' + fs + 'px Switzer, sans-serif'; o.textAlign = 'center'; o.textBaseline = 'middle'; o.fillStyle = '#000';
o.fillText('404', W / 2, H * .36);
var d = o.getImageData(0, 0, W, H).data, step = Math.max(3, Math.round(Math.min(W, H) / 68)), old = ps, k = 0; ps = [];
for (var y = 0; y < H; y += step) for (var x = 0; x < W; x += step) {
if (d[(y * W + x) * 4 + 3] > 128) {
var q = old[k++] || { x: Math.random() * W, y: Math.random() * H, vx: 0, vy: 0 };
ps.push({ x: reduce ? x : q.x, y: reduce ? y : q.y, vx: q.vx, vy: q.vy, hx: x, hy: y, o: Math.random() < .14 });
}
}
sz = step * .66; ready = true; draw();
}
function draw() {
ctx.clearRect(0, 0, W, H);
ctx.fillStyle = '#0a0a0a';
for (var i = 0; i < ps.length; i++) if (!ps[i].o) ctx.fillRect(ps[i].x, ps[i].y, sz, sz);
ctx.fillStyle = '#F5480F';
for (var j = 0; j < ps.length; j++) if (ps[j].o) ctx.fillRect(ps[j].x, ps[j].y, sz, sz);
}
function scatter() {
if (reduce) return; loose = 1;
for (var i = 0; i < ps.length; i++) { var a = Math.random() * 6.283, s = 25 + Math.random() * 45; ps[i].vx = Math.cos(a) * s; ps[i].vy = Math.sin(a) * s - 4; }
}
fit(cv, ctx, function (a, b) { W = a; H = b; if (ready) build(); });
(document.fonts && document.fonts.ready ? document.fonts.ready : Promise.resolve()).then(build);
cv.addEventListener('pointermove', function (e) { var r = cv.getBoundingClientRect(); mx = e.clientX - r.left; my = e.clientY - r.top; });
cv.addEventListener('pointerleave', function () { mx = my = -999; });
cv.addEventListener('pointerdown', scatter);
w.querySelector('.dpw__btn').addEventListener('click', scatter);
w.querySelector('.dpw__link').addEventListener('click', function (e) { e.preventDefault(); });
loop(w, function (dt) {
if (reduce || !ready) return;
var f = dt * 60, damp = Math.pow(loose > .5 ? .94 : .86, f), R = Math.min(W, H) * .22, sk = .05 * (1 - loose * .97); loose = Math.max(0, loose - dt * .9);
for (var i = 0; i < ps.length; i++) {
var p = ps[i], dx = p.x - mx, dy = p.y - my, d = Math.sqrt(dx * dx + dy * dy);
p.vx = p.vx * damp + (p.hx - p.x) * sk * f; p.vy = p.vy * damp + (p.hy - p.y) * sk * f;
if (d < R && d > .1) { var push = (1 - d / R) * 5 * f; p.vx += dx / d * push; p.vy += dy / d * push; }
p.x += p.vx * f * .5; p.y += p.vy * f * .5;
}
draw();
});
}
init(document.querySelector('.jouw-container'));
More backgrounds & webgl
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 →