Gras dat wegbuigt voor je muis Nieuw
Een strook gras met hier en daar een oranje bloem wuift in de wind en buigt opzij waar je muis of vinger doorheen gaat, en veert daarna terug. Voor de hero of de offerteknop van een hovenier, grasmaaierwinkel, camping, kinderboerderij of sportpark. Canvas 2D met een paar honderd sprieten, verticaal scrollen op een telefoon blijft werken; met minder beweging staat het gras stil.
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.
<!-- Gras dat wegbuigt voor je muis · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie -->
<div class="jouw-container">
<div class="grb">
<canvas class="grb__cv" aria-hidden="true"></canvas>
<div class="grb__txt"><p class="grb__h">Hoveniersbedrijf Groenvast, Apeldoorn</p><p class="grb__p">Nieuw gazon aanleggen vanaf € 18 per m²</p><a class="grb__btn" href="#">Vraag een offerte</a></div>
</div>
</div>/* Gras dat wegbuigt voor je muis · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie */
.grb{position:absolute;inset:0;background:#f4f3f1;font-family:Switzer,sans-serif;color:#0a0a0a;overflow:hidden}
.grb__cv{position:absolute;inset:0;width:100%;height:100%;display:block;touch-action:pan-y}
.grb__txt{position:absolute;left:16px;top:14px;right:16px;pointer-events:none}
.grb__h{margin:0;font:600 18px/1.2 Switzer,sans-serif}
.grb__p{margin:4px 0 10px;font:400 14px/1.35 Switzer,sans-serif;color:#3a3a3a}
.grb__btn{pointer-events:auto}
.grb__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:#0a0a0a;color:#fff;transition:background-color .18s,color .18s}
.grb__btn:hover{background:#F5480F;color:#0a0a0a}
.grb__btn:focus-visible{outline:2px solid #F5480F;outline-offset:3px}
@media (prefers-reduced-motion: reduce){.grb__btn{transition:none}}// Gras dat wegbuigt voor je muis · © 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('.grb'), cv = w.querySelector('.grb__cv'), ctx = cv.getContext('2d');
var W = 1, H = 1, bl = [], t = 0, mx = -999, my = -999;
var COL = ['#9dbb6e', '#6f9a48', '#4f7f33', '#3a6526'];
function make() {
bl = []; var fh = H * .42;
for (var row = 0; row < 2; row++) {
var n = Math.round(W / (row ? 2.6 : 3.6));
for (var i = 0; i < n; i++) {
var h = fh * (row ? .55 + Math.random() * .45 : .4 + Math.random() * .35);
bl.push({ x: Math.random() * W, h: h, wb: 1.4 + Math.random() * 2.2, c: row ? 1 + Math.floor(Math.random() * 3) : Math.floor(Math.random() * 2), a: 0, v: 0, ph: Math.random() * 6.283, fl: row && Math.random() < .03 });
}
}
bl.sort(function (a, b) { return a.c - b.c; });
}
function draw() {
ctx.clearRect(0, 0, W, H);
var flowers = [];
for (var c = 0; c < COL.length; c++) {
ctx.fillStyle = COL[c]; ctx.beginPath();
for (var i = 0; i < bl.length; i++) {
var b = bl[i]; if (b.c !== c) continue;
var tx = b.x + Math.sin(b.a) * b.h, ty = H - Math.cos(b.a) * b.h, cx = b.x + Math.sin(b.a * .5) * b.h * .5, cy = H - b.h * .55;
ctx.moveTo(b.x - b.wb, H); ctx.quadraticCurveTo(cx - b.wb * .4, cy, tx, ty); ctx.quadraticCurveTo(cx + b.wb * .4, cy, b.x + b.wb, H); ctx.closePath();
if (b.fl) flowers.push(tx, ty);
}
ctx.fill();
}
ctx.fillStyle = '#F5480F';
for (var k = 0; k < flowers.length; k += 2) { ctx.beginPath(); ctx.arc(flowers[k], flowers[k + 1], 3.6, 0, 6.283); ctx.fill(); }
}
fit(cv, ctx, function (a, b) { W = a; H = b; make(); draw(); });
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; });
w.querySelector('.grb__btn').addEventListener('click', function (e) { e.preventDefault(); });
loop(w, function (dt) {
if (reduce) return; t += dt;
var gust = Math.max(0, Math.sin(t * .45)) * .12;
for (var i = 0; i < bl.length; i++) {
var b = bl[i], tgt = Math.sin(t * 1.5 + b.x * .015 + b.ph * .2) * .09 + gust * Math.sin(t * .9 + b.x * .004);
var dx = b.x - mx;
if (Math.abs(dx) < 80 && my > H - b.h - 40) tgt += (dx > 0 ? 1 : -1) * (1 - Math.abs(dx) / 80) * .95;
b.v += (tgt - b.a) * 34 * dt; b.v *= Math.exp(-6 * dt); b.a += b.v * dt;
}
draw();
});
}
init(document.querySelector('.jouw-container'));
Meer uit achtergronden & webgl
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 →