Golvend duinlandschap New
Five layers of dunes in sand tones roll very slowly under an orange sun, and shift a fraction with the mouse for a sense of depth. For the hero of a beach pavilion, campsite, bike rental or seaside B&B, where a photo would be too busy. Canvas 2D with a handful of sine waves, light enough for any site; with reduced motion the landscape stands still.
Paviljoen Duinzicht, Zandvoort
Vandaag open tot 22.00 uur
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.
<!-- Golvend duinlandschap · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie -->
<div class="jouw-container">
<div class="dng">
<canvas class="dng__cv" aria-hidden="true"></canvas>
<div class="dng__txt"><p class="dng__h">Paviljoen Duinzicht, Zandvoort</p><p class="dng__p">Vandaag open tot 22.00 uur</p></div>
<a class="dng__btn" href="#">Reserveer een tafel</a>
</div>
</div>/* Golvend duinlandschap · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie */
.dng{position:absolute;inset:0;background:#fbfaf8;font-family:Switzer,sans-serif;color:#0a0a0a;overflow:hidden}
.dng__cv{position:absolute;inset:0;width:100%;height:100%;display:block}
.dng__txt{position:absolute;left:16px;top:14px;right:30%}
.dng__h{margin:0;font:600 18px/1.2 Switzer,sans-serif}
.dng__p{margin:4px 0 0;font:400 14px/1.35 Switzer,sans-serif;color:#3a3a3a}
.dng__btn{position:absolute;left:16px;bottom:14px}
.dng__btn{display:inline-flex;align-items:center;min-height:36px;padding:0 14px;border:0;border-radius:4px;font:600 14px/1 Switzer,sans-serif;cursor:pointer;text-decoration:none;background:#fff;color:#0a0a0a;transition:background-color .18s,color .18s}
.dng__btn:hover{background:#F5480F;color:#0a0a0a}
.dng__btn:focus-visible{outline:2px solid #fff;outline-offset:3px}
@media (prefers-reduced-motion: reduce){.dng__btn{transition:none}}// Golvend duinlandschap · © 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('.dng'), cv = w.querySelector('.dng__cv'), ctx = cv.getContext('2d');
var W = 1, H = 1, t = 0, px = 0, tx = 0;
var L = [
{ c: '#ecdfca', b: .58, a: .07, f: 1.2, s: .5, d: .15 },
{ c: '#e0c8a3', b: .66, a: .075, f: 1.8, s: .8, d: .3 },
{ c: '#d0aa7a', b: .74, a: .07, f: 2.5, s: 1.2, d: .5 },
{ c: '#b98552', b: .83, a: .06, f: 3.3, s: 1.7, d: .75 },
{ c: '#8c5730', b: .92, a: .045, f: 4.4, s: 2.3, d: 1 }
];
function hgt(u) { return Math.sin(u) * .55 + Math.sin(u * 2.13 + 1.7) * .28 + Math.sin(u * 4.7 + .4) * .12; }
function draw() {
ctx.fillStyle = '#fbfaf8'; ctx.fillRect(0, 0, W, H);
ctx.fillStyle = '#F5480F'; ctx.beginPath(); ctx.arc(W * .8, H * .4, Math.min(W, H) * .1, 0, 6.283); ctx.fill();
for (var i = 0; i < L.length; i++) {
var l = L[i], off = t * l.s * .06 + i * 7.3 + px * l.d * .5;
ctx.fillStyle = l.c; ctx.beginPath(); ctx.moveTo(0, H);
for (var x = 0; x <= W + 8; x += 8) ctx.lineTo(x, H * (l.b + l.a * hgt(x / W * 3.4 * l.f + off)));
ctx.lineTo(W, H); ctx.closePath(); ctx.fill();
}
}
fit(cv, ctx, function (a, b) { W = a; H = b; draw(); });
w.addEventListener('pointermove', function (e) { var r = w.getBoundingClientRect(); tx = ((e.clientX - r.left) / r.width - .5) * 2; });
w.addEventListener('pointerleave', function () { tx = 0; });
w.querySelector('.dng__btn').addEventListener('click', function (e) { e.preventDefault(); });
loop(w, function (dt) { if (reduce) return; t += dt; px += (tx - px) * Math.min(1, dt * 3); 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 →