Kies je kapper of therapeut New
Staff choice as radio cards: initials avatar, speciality, rating and the next free slot, with "No preference" first (fastest slot). Absent colleagues are disabled with the reason. A bottom bar with service, duration, price and the chosen person updates live. Real radio buttons (arrow keys work natively), styled via :has(:checked) with a JS class fallback.
How to use it
- Paste the HTML where the forms & inputs 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.
<!-- Kies je kapper of therapeut · NedDev · eigen werk. -->
<div class="jouw-container">
<form class="bmk" novalidate><fieldset class="bmk__fs"><legend class="bmk__lg">Bij wie wil je zitten? <span>Knippen en föhnen · Salon Lokken, Leiden</span></legend><div class="bmk__list"></div></fieldset><div class="bmk__bar"><p class="bmk__sum" aria-live="polite"></p><button type="submit" class="bmk__go">Kies tijd</button></div></form>
</div>/* Kies je kapper of therapeut · NedDev · eigen werk. */
.bmk{position:absolute;inset:0;display:flex;flex-direction:column;margin:0;background:#fff;font-family:'Switzer',system-ui,sans-serif;color:#0a0a0a;overflow:hidden;container-type:inline-size}
.bmk__fs{flex:1;min-height:0;margin:0;padding:9px 12px 6px;border:0;overflow:auto;min-width:0}
.bmk__lg{padding:0;margin-bottom:7px;font-size:14px;font-weight:700;line-height:1.2}
.bmk__lg span{display:block;font-size:11px;font-weight:500;color:#5c5a56}
.bmk__list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px}
.bmk__opt{position:relative;display:flex;align-items:center;gap:8px;padding:6px 8px;border:1px solid rgba(10,10,10,.18);border-radius:6px;cursor:pointer;transition:border-color .15s,background-color .15s,box-shadow .15s}
.bmk__opt input{position:absolute;opacity:0;inset:0;margin:0;cursor:pointer}
.bmk__opt:hover{border-color:#0a0a0a}
.bmk__opt:has(input:focus-visible){outline:2px solid #0a0a0a;outline-offset:2px}
.bmk__opt:has(input:checked),.bmk__opt.is-on{border-color:#0a0a0a;box-shadow:inset 0 0 0 1px #0a0a0a;background:#fbfaf8}
.bmk__opt:has(input:disabled),.bmk__opt.is-off{cursor:not-allowed;background:#fafaf9;border-style:dashed;border-color:rgba(10,10,10,.2)}
.bmk__opt:has(input:disabled) .bmk__av{filter:grayscale(1);opacity:.55}
.bmk__av{position:relative;flex:none;width:34px;height:34px;border-radius:50%;display:grid;place-items:center;font-size:12px;font-weight:700;letter-spacing:.02em}
.bmk__sc{position:absolute;right:-6px;bottom:-4px;padding:0 3px;border-radius:3px;background:#0a0a0a;color:#fff;font:600 8.5px/13px 'JetBrains Mono',monospace}
.bmk__tx{min-width:0;line-height:1.25}
.bmk__nm{display:block;font-size:12.5px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bmk__sp{display:block;font-size:10.5px;color:#5c5a56;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bmk__nx{display:block;font:500 9.5px 'JetBrains Mono',monospace;color:#1f6b38;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bmk__opt:has(input:disabled) .bmk__nx{color:#8a8781}
.bmk__chk{position:absolute;top:5px;right:6px;width:14px;height:14px;border-radius:50%;border:1.5px solid rgba(10,10,10,.3);transition:border-color .15s,background-color .15s}
.bmk__opt:has(input:checked) .bmk__chk,.bmk__opt.is-on .bmk__chk{border:4px solid #0a0a0a;background:#fff}
.bmk__opt--any .bmk__av{background:#0a0a0a;color:#fff}
.bmk__bar{display:flex;align-items:center;gap:10px;padding:7px 12px;border-top:1px solid rgba(10,10,10,.12);background:#f4f3f1}
.bmk__sum{flex:1;margin:0;font-size:11.5px;line-height:1.3;color:#5c5a56;min-width:0}
.bmk__sum b{color:#0a0a0a;font-variant-numeric:tabular-nums}
.bmk__go{flex:none;height:32px;padding:0 14px;border:1px solid #0a0a0a;border-radius:4px;background:#0a0a0a;color:#fff;font:600 12.5px 'Switzer',system-ui,sans-serif;cursor:pointer;transition:background-color .15s,color .15s,border-color .15s}
.bmk__go:hover{background:#F5480F;border-color:#F5480F;color:#0a0a0a}
.bmk__go:active{transform:translateY(1px)}
.bmk__go:focus-visible{outline:2px solid #0a0a0a;outline-offset:2px}
@container (max-width:360px){.bmk__list{grid-template-columns:1fr}}
@media (prefers-reduced-motion:reduce){.bmk *{transition:none!important}}// Kies je kapper of therapeut · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
var f=root.querySelector('.bmk');if(!f)return;
var list=f.querySelector('.bmk__list'),sum=f.querySelector('.bmk__sum');
var DAG=['zo','ma','di','wo','do','vr','za'],MK=['jan','feb','mrt','apr','mei','jun','jul','aug','sep','okt','nov','dec'];
var T=new Date();T.setHours(0,0,0,0);
function add(n){var x=new Date(T);x.setDate(x.getDate()+n);while(x.getDay()===0||x.getDay()===1)x.setDate(x.getDate()+1);return x}
function when(d,t){var lab=+d===+T?'vandaag':(+d===+new Date(T.getFullYear(),T.getMonth(),T.getDate()+1)?'morgen':DAG[d.getDay()]+' '+d.getDate()+' '+MK[d.getMonth()]);return lab+' '+t}
/* team en eerstvolgende plek: in productie uit de agenda per medewerker */
var P=[
{id:'any',nm:'Geen voorkeur',sp:'Wie het eerst kan',d:add(0),t:'15:30',any:1},
{id:'sw',nm:'Sanne de Wit',sp:'Kleur en balayage',d:add(0),t:'15:30',sc:'9,4',bg:'#fde3d8',fg:'#7a2a0c'},
{id:'ya',nm:'Yusuf Aydin',sp:'Barber, fades',d:add(1),t:'09:00',sc:'9,1',bg:'#dfe8f1',fg:'#1d3a5c'},
{id:'lj',nm:'Lotte Jansen',sp:'Krullen, curly cut',d:add(2),t:'11:15',sc:'9,6',bg:'#e3eedf',fg:'#24461b'},
{id:'dv',nm:'Daan Visser',sp:'Kort en klassiek',off:'afwezig t/m '+(function(){var d=add(5);return DAG[d.getDay()]+' '+d.getDate()+' '+MK[d.getMonth()]})(),bg:'#ece9e4',fg:'#3d3a35'}];
function ini(n){return n.split(' ').filter(function(x){return /^[A-Z]/.test(x)}).map(function(x){return x[0]}).join('').slice(0,2)}
list.innerHTML=P.map(function(p,i){var nx=p.off?p.off:'vrij '+when(p.d,p.t);
return '<label class="bmk__opt'+(p.any?' bmk__opt--any':'')+'"><input type="radio" name="bmk-p" value="'+p.id+'"'+(p.off?' disabled':'')+(i===1?' checked':'')+' aria-describedby="bmk-d'+i+'"><span class="bmk__av" aria-hidden="true"'+(p.any?'':' style="background:'+p.bg+';color:'+p.fg+'"')+'>'+(p.any?'<svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="6" cy="6" r="2.5"/><circle cx="11" cy="7" r="2"/><path d="M1.5 14c.6-2.6 2.3-4 4.5-4s3.9 1.4 4.5 4M10.5 10.2c1.8.1 3.2 1.3 3.8 3.3"/></svg>':ini(p.nm))+(p.sc?'<span class="bmk__sc" title="Gemiddeld rapportcijfer">'+p.sc+'</span>':'')+'</span><span class="bmk__tx"><span class="bmk__nm">'+p.nm+'</span><span class="bmk__sp">'+p.sp+'</span><span class="bmk__nx" id="bmk-d'+i+'">'+nx+'</span></span><span class="bmk__chk" aria-hidden="true"></span></label>'}).join('');
function update(){var c=f.querySelector('input:checked');f.querySelectorAll('.bmk__opt').forEach(function(l){var i=l.querySelector('input');l.classList.toggle('is-on',i.checked);l.classList.toggle('is-off',i.disabled)});
var p=P.filter(function(x){return c&&x.id===c.value})[0];sum.innerHTML='<b>€ 42,50</b> · 45 min · '+(p?(p.any?'eerste vrije kapper, '+when(p.d,p.t):'met '+p.nm.split(' ')[0]+', vanaf '+when(p.d,p.t)):'kies een medewerker')}
f.addEventListener('change',update);
f.addEventListener('submit',function(e){e.preventDefault();var c=f.querySelector('input:checked');if(!c)return;var b=f.querySelector('.bmk__go');b.textContent='Agenda laden';b.disabled=true;setTimeout(function(){b.disabled=false;b.textContent='Kies tijd';sum.innerHTML='<b>Volgende stap:</b> tijden van '+(c.value==='any'?'alle kappers':P.filter(function(x){return x.id===c.value})[0].nm)+' worden getoond.'},600)});
update();
}
init(document.querySelector('.jouw-container'));
More forms & inputs
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 →