Beoordeling met een gezicht dat meeverandert New
A short rating with a drawn face (own SVG, no emoji) that morphs smoothly from grumpy to beaming as you move the slider from 1 to 5: mouth, brows, eyes and colour move along, and now and then it blinks. After sending it hops once. A plain range input, so arrow keys work and the value is read out as a word. Use it after an appointment, delivery or support contact.
Hoe was je afspraak bij Fysio Leidsche Rijn?
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.
<!-- Beoordeling met een gezicht dat meeverandert · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie -->
<div class="jouw-container">
<div class="k7m">
<div class="k7m__card">
<svg class="k7m__face" viewBox="0 0 100 100" aria-hidden="true"><circle class="k7m__head" cx="50" cy="50" r="46"/><circle class="k7m__ck" cx="25" cy="60" r="7"/><circle class="k7m__ck" cx="75" cy="60" r="7"/><path class="k7m__ln k7m__bl"/><path class="k7m__ln k7m__br"/><ellipse class="k7m__eye" cx="36" cy="42" rx="4.5" ry="6"/><ellipse class="k7m__eye" cx="64" cy="42" rx="4.5" ry="6"/><path class="k7m__ln k7m__mouth"/></svg>
<div class="k7m__side">
<p class="k7m__q">Hoe was je afspraak bij Fysio Leidsche Rijn?</p>
<p class="k7m__word" aria-hidden="true">Gaat wel</p>
<input class="k7m__range" type="range" min="1" max="5" step="1" value="3" aria-label="Beoordeling van 1 tot 5" aria-valuetext="3 van 5, gaat wel">
<button class="k7m__send" type="button">Verstuur</button>
<p class="k7m__st" role="status"></p>
</div>
</div>
</div>
</div>/* Beoordeling met een gezicht dat meeverandert · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie */
.k7m{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;box-sizing:border-box;font-family:'Switzer',system-ui,sans-serif;color:#0a0a0a;text-align:left;padding:12px}
.k7m *{box-sizing:border-box}
.k7m__card{display:flex;align-items:center;gap:16px;width:100%;max-width:370px}
.k7m__face{flex:none;width:100px;height:100px;overflow:visible}
.k7m__face.is-jump{animation:k7m-jump .6s cubic-bezier(.3,1.5,.5,1)}
@keyframes k7m-jump{30%{transform:translateY(-12px) rotate(-6deg)}65%{transform:translateY(0) rotate(4deg)}}
.k7m__eye{fill:#0a0a0a}
.k7m__ck{fill:#b8360a}
.k7m__ln{fill:none;stroke:#0a0a0a;stroke-width:3.6;stroke-linecap:round}
.k7m__side{flex:1;min-width:0}
.k7m__q{margin:0 0 4px;font-size:13px;font-weight:600;line-height:1.35}
.k7m__word{margin:0;font-size:20px;font-weight:700;line-height:1.25}
.k7m__range{display:block;width:100%;height:28px;margin:2px 0 8px;background:none;-webkit-appearance:none;appearance:none;cursor:pointer}
.k7m__range::-webkit-slider-runnable-track{height:4px;background:#d9d5cf;border-radius:2px}
.k7m__range::-webkit-slider-thumb{-webkit-appearance:none;width:24px;height:24px;margin-top:-10px;border:2px solid #0a0a0a;border-radius:4px;background:#fff}
.k7m__range::-moz-range-track{height:4px;background:#d9d5cf;border-radius:2px}
.k7m__range::-moz-range-thumb{width:20px;height:20px;border:2px solid #0a0a0a;border-radius:4px;background:#fff}
.k7m__range:focus-visible{outline:2px solid #F5480F;outline-offset:3px}
.k7m__send{height:32px;padding:0 14px;border:0;border-radius:4px;background:#0a0a0a;color:#fff;font:600 13px/1 'Switzer',system-ui,sans-serif;cursor:pointer;transition:background-color .15s}
.k7m__send:hover{background:#333}
.k7m__send:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.k7m__st{margin:6px 0 0;min-height:17px;font-size:12px;line-height:1.4;color:#4d4d4d}
@media (prefers-reduced-motion:reduce){.k7m__face.is-jump{animation:none}}// Beoordeling met een gezicht dat meeverandert · © 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 w = root.querySelector('.k7m'); if (!w) return;
var face = w.querySelector('.k7m__face'), head = w.querySelector('.k7m__head'), eyes = w.querySelectorAll('.k7m__eye'), cks = w.querySelectorAll('.k7m__ck');
var bl = w.querySelector('.k7m__bl'), br = w.querySelector('.k7m__br'), mouth = w.querySelector('.k7m__mouth');
var word = w.querySelector('.k7m__word'), rng = w.querySelector('.k7m__range'), send = w.querySelector('.k7m__send'), st = w.querySelector('.k7m__st');
var WD = ['Slecht', 'Matig', 'Gaat wel', 'Goed', 'Top'], rm = matchMedia('(prefers-reduced-motion: reduce)').matches;
var v = 3, d = 3, raf = 0, blink = 1;
function mix(a, b, t) { return Math.round(a + (b - a) * t); }
function render() {
var t = Math.pow((d - 1) / 4, 1.3);
head.setAttribute('fill', 'rgb(' + mix(217, 245, t) + ',' + mix(213, 72, t) + ',' + mix(207, 15, t) + ')');
var k = -14 + 8 * (d - 1), y = 68 - Math.max(0, k) * .25, hw = 14 + (d - 1) * 1.6;
mouth.setAttribute('d', 'M' + (50 - hw).toFixed(1) + ' ' + y.toFixed(1) + ' Q50 ' + (y + 2 * k).toFixed(1) + ' ' + (50 + hw).toFixed(1) + ' ' + y.toFixed(1));
var tilt = Math.max(0, (3 - d) / 2), lift = Math.max(0, d - 3) * 1.5, o = 30 + tilt * 1.5 - lift, i = 30 - tilt * 4 - lift;
bl.setAttribute('d', 'M27 ' + o.toFixed(1) + ' L43 ' + i.toFixed(1)); br.setAttribute('d', 'M57 ' + i.toFixed(1) + ' L73 ' + o.toFixed(1));
var ry = (6 - Math.max(0, d - 3.5) * 2) * blink;
eyes.forEach(function (e) { e.setAttribute('ry', Math.max(.4, ry).toFixed(2)); });
var c = Math.max(0, Math.min(1, (d - 3.6) / 1.4)) * .5;
cks.forEach(function (e) { e.setAttribute('opacity', c.toFixed(2)); });
}
function tick() { d += (v - d) * .2; if (Math.abs(v - d) < .01) d = v; render(); raf = d !== v ? requestAnimationFrame(tick) : 0; }
rng.addEventListener('input', function () {
v = +rng.value; word.textContent = WD[v - 1];
rng.setAttribute('aria-valuetext', v + ' van 5, ' + WD[v - 1].toLowerCase());
send.textContent = 'Verstuur'; st.textContent = '';
if (rm) { d = v; render(); } else if (!raf) raf = requestAnimationFrame(tick);
});
send.addEventListener('click', function () {
st.textContent = 'Bedankt. Je gaf een ' + v + ' van 5: ' + WD[v - 1].toLowerCase() + '.';
send.textContent = 'Verstuurd';
face.classList.remove('is-jump'); void face.getBoundingClientRect(); face.classList.add('is-jump');
});
if (!rm) {
(function knipper() {
setTimeout(function () {
if (!w.isConnected) return;
blink = .08; render(); setTimeout(function () { blink = 1; render(); knipper(); }, 130);
}, 3200 + Math.random() * 2400);
})();
}
render();
}
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 →