Configurator met meerprijs New
Product configurator for a dormer: width, frame and glazing as option rows with the surcharge per option, extras as checkboxes, and a summary listing each chosen surcharge and a VAT-inclusive total that counts to the new amount. Real radios and checkboxes in fieldsets (arrows and Space work), :has(:checked) for the selected state with a JS class fallback, aria-live on the total. After "Request quote" a loading and success state. Prices are example amounts.
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.
<!-- Configurator met meerprijs · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="bcm-q"><form class="bcm" novalidate><div class="bcm__opts"><p class="bcm__h">Stel je dakkapel samen</p></div><div class="bcm__side"><p class="bcm__k">Jouw dakkapel</p><ul class="bcm__lines"></ul><p class="bcm__tot"><span>Totaal incl. 21% btw</span><b class="bcm__t" aria-live="polite"></b></p><p class="bcm__inc">Incl. montage in 1 dag en steiger</p><button type="submit" class="bcm__go">Offerte aanvragen</button><p class="bcm__st" role="status"></p></div></form></div>
</div>/* Configurator met meerprijs · NedDev · eigen werk. */
.bcm-q{position:absolute;inset:0;container-type:inline-size}
.bcm{position:absolute;inset:0;margin:0;display:grid;grid-template-columns:minmax(0,1fr) 150px;background:#fff;font-family:'Switzer',system-ui,sans-serif;color:#0a0a0a;overflow:hidden}
.bcm__opts{padding:10px 12px;overflow:auto;overscroll-behavior:contain}
.bcm__h{margin:0 0 6px;font-size:14px;font-weight:700}
.bcm__fs{margin:0 0 8px;padding:0;border:0;min-width:0}
.bcm__fs legend{padding:0;margin-bottom:4px;font:500 9.5px 'JetBrains Mono',monospace;text-transform:uppercase;letter-spacing:.07em;color:#5c5a56}
.bcm__seg{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:4px}
.bcm__o{position:relative;display:block;cursor:pointer}
.bcm__o input{position:absolute;inset:0;opacity:0;margin:0;cursor:pointer}
.bcm__o span{display:block;padding:4px 6px;border:1px solid rgba(10,10,10,.2);border-radius:4px;font-size:12px;font-weight:600;line-height:1.2;transition:border-color .15s,background-color .15s,box-shadow .15s}
.bcm__o small{display:block;font-size:10px;font-weight:500;color:#5c5a56;font-variant-numeric:tabular-nums}
.bcm__o:hover span{border-color:#0a0a0a}
.bcm__o input:focus-visible+span{outline:2px solid #0a0a0a;outline-offset:2px}
.bcm__o input:checked+span,.bcm__o.is-on span{border-color:#0a0a0a;box-shadow:inset 0 0 0 1px #0a0a0a;background:#fbfaf8}
.bcm__o input:checked+span small,.bcm__o.is-on span small{color:#0a0a0a}
.bcm__x{display:grid;gap:3px}
.bcm__c{display:flex;align-items:center;gap:7px;padding:3px 0;font-size:12px;cursor:pointer}
.bcm__c input{width:14px;height:14px;margin:0;accent-color:#0a0a0a;cursor:pointer}
.bcm__c input:focus-visible{outline:2px solid #0a0a0a;outline-offset:2px}
.bcm__c em{margin-left:auto;font-style:normal;font-size:11px;color:#5c5a56;font-variant-numeric:tabular-nums}
.bcm__side{display:flex;flex-direction:column;padding:10px 12px;background:#0a0a0a;color:#fff;min-height:0;overflow:auto}
.bcm__k{margin:0 0 6px;font:500 9.5px 'JetBrains Mono',monospace;text-transform:uppercase;letter-spacing:.07em;color:#bdbab4}
.bcm__lines{margin:0;padding:0;list-style:none;font-size:11px;line-height:1.3}
.bcm__lines li{display:flex;justify-content:space-between;gap:6px;padding:2px 0;color:#d9d6d0}
.bcm__lines li b{font-weight:500;color:#fff;font-variant-numeric:tabular-nums;white-space:nowrap}
.bcm__lines li.is-new{animation:bcm-in .35s ease}
@keyframes bcm-in{from{background:rgba(245,72,15,.35)}}
.bcm__tot{margin:8px 0 0;padding-top:7px;border-top:1px solid rgba(255,255,255,.2)}
.bcm__tot span{display:block;font-size:10px;color:#bdbab4}
.bcm__tot b{font-size:19px;font-weight:700;font-variant-numeric:tabular-nums}
.bcm__inc{margin:2px 0 8px;font-size:10px;color:#bdbab4}
.bcm__go{margin-top:auto;height:32px;border:0;border-radius:4px;background:#F5480F;color:#0a0a0a;font:700 12px 'Switzer',system-ui,sans-serif;cursor:pointer;transition:background-color .15s,color .15s}
.bcm__go:hover:not(:disabled){background:#fff}
.bcm__go:active:not(:disabled){transform:translateY(1px)}
.bcm__go:focus-visible{outline:2px solid #fff;outline-offset:2px}
.bcm__go:disabled{opacity:.7;cursor:progress}
.bcm__st{margin:5px 0 0;font-size:10.5px;line-height:1.3;color:#9fd8b1}
.bcm__st:empty{display:none}
@container (max-width:380px){.bcm{grid-template-columns:1fr;grid-template-rows:minmax(0,1fr) auto}.bcm__side{display:grid;grid-template-columns:1fr auto;align-items:center;gap:2px 10px;padding:8px 12px}.bcm__k,.bcm__lines,.bcm__inc{display:none}.bcm__tot{margin:0;padding:0;border:0}.bcm__go{margin:0;padding:0 12px}.bcm__st{grid-column:1/-1}}
@media (prefers-reduced-motion:reduce){.bcm *{transition:none!important;animation:none!important}}// Configurator met meerprijs · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
var f=root.querySelector('.bcm');if(!f)return;
var opts=f.querySelector('.bcm__opts'),lines=f.querySelector('.bcm__lines'),tEl=f.querySelector('.bcm__t'),go=f.querySelector('.bcm__go'),st=f.querySelector('.bcm__st');
/* voorbeeldprijzen incl. btw */
var BASE=7950,G=[
{k:'br',t:'Breedte',o:[['2 m','',0],['3 m','',1500],['4 m','',3150]]},
{k:'kz',t:'Kozijn',o:[['Wit','kunststof',0],['Antraciet','kunststof',450],['Hout','meranti',1250]]},
{k:'gl',t:'Glas',o:[['HR++','',0],['Triple','',690],['Zonwerend','',380]]}],
X=[['rl','Rolluiken, elektrisch',1190],['hr','Horren',180],['vr','Ventilatieroosters',95]];
var shown=0,raf=0,prev={};
function eur(n){return '€ '+Math.round(n).toLocaleString('nl-NL')}
function plus(n){return n?'+'+eur(n):'inbegrepen'}
opts.insertAdjacentHTML('beforeend',G.map(function(g){return '<fieldset class="bcm__fs"><legend>'+g.t+'</legend><div class="bcm__seg">'+g.o.map(function(o,i){return '<label class="bcm__o"><input type="radio" name="bcm-'+g.k+'" value="'+i+'"'+(i===(g.k==='br'?1:0)?' checked':'')+' aria-label="'+o[0]+(o[1]?' '+o[1]:'')+', '+plus(o[2])+'"><span>'+o[0]+'<small>'+plus(o[2])+'</small></span></label>'}).join('')+'</div></fieldset>'}).join('')+
'<fieldset class="bcm__fs"><legend>Extra</legend><div class="bcm__x">'+X.map(function(x,i){return '<label class="bcm__c"><input type="checkbox" name="bcm-'+x[0]+'"'+(i===0?' checked':'')+'>'+x[1]+'<em>+'+eur(x[2])+'</em></label>'}).join('')+'</div></fieldset>');
function setTotal(to){cancelAnimationFrame(raf);if(!shown||matchMedia('(prefers-reduced-motion:reduce)').matches){shown=to;tEl.textContent=eur(to);return}var from=shown,t0=performance.now();(function s(t){var k=Math.min(1,(t-t0)/420),e=1-Math.pow(1-k,3);shown=from+(to-from)*e;tEl.textContent=eur(shown);if(k<1)raf=requestAnimationFrame(s)})(t0)}
function calc(){var L=[['Dakkapel basis, 2 m',BASE]],tot=BASE;
G.forEach(function(g){var i=+f.querySelector('input[name="bcm-'+g.k+'"]:checked').value,o=g.o[i];if(o[2]){L.push([g.t+': '+o[0],o[2]]);tot+=o[2]}});
X.forEach(function(x){if(f.querySelector('input[name="bcm-'+x[0]+'"]').checked){L.push([x[1],x[2]]);tot+=x[2]}});
var now={};lines.innerHTML=L.map(function(l,i){now[l[0]]=1;return '<li'+(i&&!prev[l[0]]&&Object.keys(prev).length?' class="is-new"':'')+'><span>'+l[0]+'</span><b>'+(i?'+':'')+eur(l[1])+'</b></li>'}).join('');prev=now;
f.querySelectorAll('.bcm__o').forEach(function(o){o.classList.toggle('is-on',o.querySelector('input').checked)});
setTotal(tot);go.disabled=false;go.textContent='Offerte aanvragen';st.textContent=''}
f.addEventListener('change',calc);
f.addEventListener('submit',function(e){e.preventDefault();go.disabled=true;go.textContent='Versturen';setTimeout(function(){go.textContent='Aangevraagd';st.textContent='Binnen 2 werkdagen bellen we om de inmeetafspraak te plannen.'},800)});
calc();
}
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 →