Uil die meekijkt bij inloggen New
Login screen with an owl mascot: its eyes follow the mouse across the whole page, watch while you type your email address, and the owl covers its eyes with its wings as soon as you enter your password (with "Show" it peeks with one eye). Works fully with the keyboard, because the eyes also follow focus. For a childcare parent portal, a sports club member area or the customer login of a playful web shop.
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.
<!-- Uil die meekijkt bij inloggen · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie -->
<div class="jouw-container">
<div class="mso">
<svg class="mso__uil" viewBox="0 0 120 132" aria-hidden="true">
<path d="M22 34 L30 9 L45 27 Z M98 34 L90 9 L75 27 Z" fill="#0a0a0a"/>
<path d="M60 18 C92 18 104 42 104 72 C104 106 86 126 60 126 C34 126 16 106 16 72 C16 42 28 18 60 18 Z" fill="#0a0a0a"/>
<ellipse cx="60" cy="100" rx="25" ry="20" fill="#2b2926"/>
<path d="M50 96 q4 4 8 0 M62 96 q4 4 8 0 M56 106 q4 4 8 0" stroke="#5a5650" stroke-width="2" fill="none" stroke-linecap="round"/>
<circle cx="42" cy="56" r="18" fill="#fff"/><circle cx="78" cy="56" r="18" fill="#fff"/>
<g transform="translate(42 56)"><g class="mso__oog"><circle r="8" fill="#0a0a0a"/><circle cx="-3" cy="-3" r="2.4" fill="#fff"/></g></g>
<g transform="translate(78 56)"><g class="mso__oog"><circle r="8" fill="#0a0a0a"/><circle cx="-3" cy="-3" r="2.4" fill="#fff"/></g></g>
<path d="M54 70 L66 70 L60 81 Z" fill="#F5480F"/>
<ellipse cx="48" cy="127" rx="7" ry="3.5" fill="#F5480F"/><ellipse cx="72" cy="127" rx="7" ry="3.5" fill="#F5480F"/>
<ellipse class="mso__vleugel mso__vleugel--l" cx="42" cy="58" rx="21" ry="17" fill="#F5480F"/>
<ellipse class="mso__vleugel mso__vleugel--r" cx="78" cy="58" rx="21" ry="17" fill="#F5480F"/>
</svg>
<form class="mso__form" novalidate>
<p class="mso__kop">Ouderportaal Het Uilennest</p>
<label class="mso__lbl" for="mso-mail">E-mailadres</label>
<input class="mso__in mso__mail" id="mso-mail" type="email" autocomplete="off" spellcheck="false" placeholder="naam@voorbeeld.nl">
<label class="mso__lbl" for="mso-ww">Wachtwoord</label>
<div class="mso__wwrij"><input class="mso__in mso__ww" id="mso-ww" type="password" autocomplete="off"><button type="button" class="mso__toon" aria-pressed="false" aria-label="Wachtwoord tonen">Toon</button></div>
<button type="submit" class="mso__knop">Inloggen</button>
<p class="mso__sr" aria-live="polite"></p>
</form>
</div>
</div>/* Uil die meekijkt bij inloggen · © 2026 NedDev BV · NedDev Lab-licentie (gratis gebruik, niet doorverkopen) · neddev.com/nl/lab/gebruik/#licentie */
.mso{width:100%;height:100%;display:flex;align-items:center;justify-content:center;gap:16px;padding:12px 16px;box-sizing:border-box;background:#f4f3f1;font-family:Switzer,sans-serif}
.mso__uil{flex:0 0 auto;width:min(30%,118px);height:auto;overflow:hidden}
.mso__oog{transition:transform .09s linear}
.mso__vleugel{transform:translateY(80px);transition:transform .3s cubic-bezier(.3,1.4,.5,1)}
.mso.is-dicht .mso__vleugel{transform:translateY(0)}
.mso.is-gluur .mso__vleugel--r{transform:translateY(17px)}
.mso.is-blij .mso__oog{transform:scaleY(.25)}
.mso.is-knipper .mso__oog{transform:scaleY(.1)}
.mso__form{flex:1 1 auto;max-width:230px;display:flex;flex-direction:column;min-width:0}
.mso__kop{margin:0 0 6px;font-size:15px;font-weight:600;color:#0a0a0a;line-height:1.2}
.mso__lbl{font-size:12px;color:#55524d;margin:4px 0 2px}
.mso__in{font:inherit;font-size:14px;height:30px;padding:0 8px;border:1px solid #c9c6c0;border-radius:4px;background:#fff;color:#0a0a0a;min-width:0;width:100%;box-sizing:border-box}
.mso__in:focus{outline:2px solid #F5480F;outline-offset:0;border-color:#F5480F}
.mso__wwrij{display:flex;gap:6px}
.mso__toon{font:inherit;font-size:13px;height:30px;padding:0 9px;border:1px solid #0a0a0a;border-radius:4px;background:#fff;color:#0a0a0a;cursor:pointer}
.mso__toon[aria-pressed="true"]{background:#0a0a0a;color:#fff}
.mso__knop{font:inherit;font-size:14px;font-weight:600;height:32px;margin-top:10px;border:0;border-radius:4px;background:#0a0a0a;color:#fff;cursor:pointer;transition:background-color .15s}
.mso__knop:hover{background:#F5480F}
.mso__toon:focus-visible,.mso__knop:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.mso__sr{position:absolute;width:1px;height:1px;margin:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
@media (prefers-reduced-motion:reduce){.mso__oog,.mso__vleugel{transition:none}}// Uil die meekijkt bij inloggen · © 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){
const w = root.querySelector('.mso'); if (!w) return;
const svg = w.querySelector('.mso__uil'), ogen = w.querySelectorAll('.mso__oog');
const mail = w.querySelector('.mso__mail'), ww = w.querySelector('.mso__ww'), toon = w.querySelector('.mso__toon');
const form = w.querySelector('.mso__form'), sr = w.querySelector('.mso__sr'), knop = w.querySelector('.mso__knop');
const rm = matchMedia('(prefers-reduced-motion: reduce)').matches;
const C = [[42, 56], [78, 56]];
let zichtbaar = true;
function kijk(px, py){
const r = svg.getBoundingClientRect(); if (!r.width) return; const s = r.width / 120;
ogen.forEach((o, i) => {
const ex = r.left + C[i][0] * s, ey = r.top + C[i][1] * s;
const dx = px - ex, dy = py - ey, d = Math.hypot(dx, dy) || 1;
const m = Math.min(7, d / (14 * s));
o.style.transform = 'translate(' + (dx / d * m).toFixed(2) + 'px,' + (dy / d * m).toFixed(2) + 'px)';
});
}
function naarVeld(inp){
const r = inp.getBoundingClientRect();
const x = r.left + Math.min(r.width - 8, 10 + inp.value.length * 7.5);
kijk(x, r.top + r.height / 2);
}
document.addEventListener('pointermove', e => {
if (!zichtbaar || w.classList.contains('is-blij')) return;
const a = document.activeElement; if (a === mail || a === ww) return;
kijk(e.clientX, e.clientY);
}, { passive: true });
function stand(){
const a = document.activeElement;
const dicht = a === ww || (a === toon && ww.value.length > 0);
const gluur = dicht && toon.getAttribute('aria-pressed') === 'true';
w.classList.toggle('is-dicht', dicht); w.classList.toggle('is-gluur', gluur);
if (a === mail || a === ww) naarVeld(a);
else if (a && w.contains(a)) { const r = a.getBoundingClientRect(); kijk(r.left + r.width / 2, r.top + r.height / 2); }
}
w.addEventListener('focusin', stand);
w.addEventListener('focusout', () => setTimeout(stand, 0));
mail.addEventListener('input', () => naarVeld(mail));
ww.addEventListener('input', () => naarVeld(ww));
toon.addEventListener('click', () => {
const op = toon.getAttribute('aria-pressed') !== 'true';
toon.setAttribute('aria-pressed', String(op)); toon.setAttribute('aria-label', op ? 'Wachtwoord verbergen' : 'Wachtwoord tonen');
toon.textContent = op ? 'Verberg' : 'Toon'; ww.type = op ? 'text' : 'password'; ww.focus(); stand();
});
form.addEventListener('submit', e => {
e.preventDefault();
if (!mail.value.includes('@')) { sr.textContent = 'Vul een e-mailadres in.'; mail.focus(); return; }
w.classList.remove('is-dicht', 'is-gluur'); w.classList.add('is-blij');
knop.textContent = 'Welkom terug'; sr.textContent = 'Demo: je bent ingelogd.';
setTimeout(() => { w.classList.remove('is-blij'); knop.textContent = 'Inloggen'; }, 2200);
});
if (!rm) {
(function knipper(){
setTimeout(() => {
if (zichtbaar && !w.classList.contains('is-dicht') && !w.classList.contains('is-blij')) {
const bewaar = [...ogen].map(o => o.style.transform);
ogen.forEach((o, i) => { o.style.transform = (bewaar[i] || '') + ' scaleY(.1)'; });
setTimeout(() => ogen.forEach((o, i) => { o.style.transform = bewaar[i]; }), 120);
}
knipper();
}, 3200 + Math.random() * 2600);
})();
}
if ('IntersectionObserver' in window) new IntersectionObserver(es => { zichtbaar = es[0].isIntersecting; }).observe(w);
}
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 →