Hero met boekbalk als onderrand New
Photo hero for an event venue or hotel with a booking bar over its bottom edge: date range, guests and event type. Shows loading, error (end before start), empty (too many guests) and results with available rooms. Native date inputs, no datepicker library; in production wire the search to your booking system.
Remise Oost · Zaandam · 3 zalen tot 650 gasten
Een zaal aan de Zaan voor uw jubileum, congres of personeelsfeest.
Voormalige tramremise uit 1911, 12 minuten van Amsterdam Centraal. Eigen keuken, gratis parkeren voor 140 auto’s.
How to use it
- Paste the HTML where the page sections 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.
<!-- Hero met boekbalk als onderrand · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="bbh">
<div class="bbh__hero">
<img class="bbh__img" src="https://neddev.com/lab-media/boekbalk-hero-rand-1.webp" alt="Ketelhuis van Remise Oost, gedekt voor een diner met lange tafels" loading="lazy">
<div class="bbh__copy">
<p class="bbh__eyebrow">Remise Oost · Zaandam · 3 zalen tot 650 gasten</p>
<h2 class="bbh__h">Een zaal aan de Zaan voor uw jubileum, congres of personeelsfeest.</h2>
<p class="bbh__lead">Voormalige tramremise uit 1911, 12 minuten van Amsterdam Centraal. Eigen keuken, gratis parkeren voor 140 auto’s.</p>
</div>
</div>
<form class="bbh__bar" novalidate aria-label="Beschikbaarheid zoeken">
<div class="bbh__f bbh__f--date"><label for="bbh-van">Van</label><input id="bbh-van" class="bbh__in" type="date" value="2026-11-13" min="2026-10-07" required></div>
<div class="bbh__f bbh__f--date"><label for="bbh-tot">Tot en met</label><input id="bbh-tot" class="bbh__in" type="date" value="2026-11-13" min="2026-10-07" required aria-describedby="bbh-err"></div>
<div class="bbh__f"><label for="bbh-n">Gasten</label>
<div class="bbh__step"><button type="button" class="bbh__sb" data-d="-10" aria-label="10 gasten minder">-</button><input id="bbh-n" class="bbh__in bbh__num" type="number" inputmode="numeric" min="10" max="2000" step="10" value="120"><button type="button" class="bbh__sb" data-d="10" aria-label="10 gasten meer">+</button></div>
</div>
<div class="bbh__f"><label for="bbh-soort">Soort</label>
<select id="bbh-soort" class="bbh__in"><option>Diner</option><option>Congres</option><option>Feest</option><option>Vergadering</option></select>
</div>
<button type="submit" class="bbh__go"><span class="bbh__spin" aria-hidden="true"></span><span class="bbh__go-lbl">Bekijk vrije zalen</span></button>
<p class="bbh__err" id="bbh-err" role="alert"></p>
</form>
<div class="bbh__out" aria-live="polite">
<p class="bbh__range"></p>
<div class="bbh__res"></div>
</div>
</div>
</div>/* Hero met boekbalk als onderrand · NedDev · eigen werk. */
/* fonts (Fontshare): boska@400,500 + satoshi@400,500,700 */
.bbh{--ink:#231a15;--mut:#6b5e54;--cream:#f6f1e8;--line:#e0d5c4;--cop:#9e4f20;--cop2:#843f15;background:var(--cream);color:var(--ink);font-family:'Satoshi','Switzer',sans-serif;box-sizing:border-box;padding-bottom:28px}
.bbh *,.bbh *::before{box-sizing:border-box}
.bbh__hero{position:relative;height:440px;overflow:hidden;background:#2a1d17}
.bbh__img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:50% 60%}
.bbh__hero::after{content:'';position:absolute;inset:0;background:linear-gradient(90deg,rgba(25,16,11,.82) 0%,rgba(25,16,11,.5) 48%,rgba(25,16,11,.05) 80%)}
.bbh__copy{position:relative;z-index:1;max-width:1180px;margin:0 auto;padding:58px 40px 0;color:#fff}
.bbh__eyebrow{margin:0 0 14px;font:500 11px/1 'JetBrains Mono',monospace;letter-spacing:.12em;text-transform:uppercase;color:#f0c9a8}
.bbh__h{margin:0 0 14px;font-family:'Boska',Georgia,serif;font-weight:500;font-size:clamp(30px,4vw,50px);line-height:1.04;max-width:20ch}
.bbh__lead{margin:0;font-size:16px;line-height:1.55;max-width:44ch;color:rgba(255,255,255,.86)}
.bbh__bar{position:relative;z-index:2;max-width:1100px;margin:-62px auto 0;background:#fff;border-radius:6px;box-shadow:0 18px 40px -18px rgba(35,26,21,.45);display:grid;grid-template-columns:1fr 1fr 170px 150px auto;align-items:stretch;padding:8px}
.bbh__f{display:flex;flex-direction:column;justify-content:center;gap:3px;padding:8px 14px;border-right:1px solid var(--line);min-width:0}
.bbh__f label{font:500 10.5px 'JetBrains Mono',monospace;letter-spacing:.1em;text-transform:uppercase;color:var(--mut)}
.bbh__in{width:100%;min-width:0;font:600 16px 'Satoshi',sans-serif;color:var(--ink);background:transparent;border:0;border-radius:3px;padding:4px 2px;outline:none}
.bbh__in:focus-visible{box-shadow:0 0 0 2px var(--cop)}
.bbh__in[aria-invalid="true"]{color:#a2231a;box-shadow:0 0 0 2px #a2231a}
.bbh__step{display:flex;align-items:center;gap:4px}
.bbh__num{text-align:center;-moz-appearance:textfield;font-variant-numeric:tabular-nums}
.bbh__num::-webkit-inner-spin-button,.bbh__num::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}
.bbh__sb{flex:none;width:28px;height:28px;border-radius:50%;border:1px solid var(--line);background:#fff;color:var(--ink);font:600 16px/1 'Satoshi',sans-serif;cursor:pointer;transition:background-color .15s ease,border-color .15s ease}
.bbh__sb:hover{border-color:var(--ink)}
.bbh__sb:active{background:var(--cream)}
.bbh__sb:focus-visible{outline:2px solid var(--cop);outline-offset:2px}
.bbh__go{display:inline-flex;align-items:center;justify-content:center;gap:8px;margin-left:8px;padding:0 24px;border:0;border-radius:4px;background:var(--cop);color:#fff;font:700 15px 'Satoshi',sans-serif;cursor:pointer;white-space:nowrap;transition:background-color .15s ease}
.bbh__go:hover{background:var(--cop2)}
.bbh__go:active{transform:translateY(1px)}
.bbh__go:focus-visible{outline:3px solid var(--ink);outline-offset:2px}
.bbh__go[aria-busy="true"]{cursor:progress;background:#b9805c}
.bbh__spin{display:none;width:15px;height:15px;border:2px solid rgba(255,255,255,.4);border-top-color:#fff;border-radius:50%;animation:bbh-spin .7s linear infinite}
.bbh__go[aria-busy="true"] .bbh__spin{display:inline-block}
@keyframes bbh-spin{to{transform:rotate(360deg)}}
.bbh__err{grid-column:1/-1;margin:0;font-size:13.5px;color:#a2231a;font-weight:500}
.bbh__err:not(:empty){padding:8px 14px 4px}
.bbh__out{max-width:1100px;margin:16px auto 0;padding:0 8px}
.bbh__range{margin:0 0 10px;font:500 12px 'JetBrains Mono',monospace;letter-spacing:.04em;color:var(--mut)}
.bbh__res{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.bbh__room{background:#fff;border:1px solid var(--line);border-radius:5px;padding:14px 16px;display:flex;flex-direction:column;gap:4px}
.bbh__room b{font-family:'Boska',Georgia,serif;font-weight:500;font-size:20px}
.bbh__room span{font-size:13.5px;color:var(--mut)}
.bbh__room strong{font-size:15px;font-variant-numeric:tabular-nums;margin-top:4px}
.bbh__opt{align-self:flex-start;margin-top:8px;font:700 13.5px 'Satoshi',sans-serif;color:var(--cop);background:transparent;border:1.5px solid var(--cop);border-radius:4px;padding:7px 12px;cursor:pointer;transition:background-color .15s ease,color .15s ease}
.bbh__opt:hover{background:var(--cop);color:#fff}
.bbh__opt:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
.bbh__opt[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:#fff}
.bbh__room--off{background:transparent;border-style:dashed}
.bbh__msg{grid-column:1/-1;background:#fff;border:1px dashed var(--line);border-radius:5px;padding:14px 16px;font-size:14.5px;line-height:1.5}
@media (max-width:900px){
.bbh__hero{height:400px}
.bbh__hero::after{background:linear-gradient(180deg,rgba(25,16,11,.78) 0%,rgba(25,16,11,.6) 70%,rgba(25,16,11,.4) 100%)}
.bbh__copy{padding:34px 18px 0}
.bbh__bar{margin:-46px 12px 0;grid-template-columns:1fr 1fr;padding:6px}
.bbh__f{border-right:0;border-bottom:1px solid var(--line);padding:8px 10px}
.bbh__go{grid-column:1/-1;margin:8px 0 2px;padding:14px}
.bbh__out{padding:0 12px}
.bbh__res{grid-template-columns:1fr}
}
@media (prefers-reduced-motion:reduce){.bbh *{transition:none!important}.bbh__spin{animation-duration:2s}}// Hero met boekbalk als onderrand · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
const w=root.querySelector('.bbh'); if(!w) return;
const f=w.querySelector('.bbh__bar'), van=w.querySelector('#bbh-van'), tot=w.querySelector('#bbh-tot'), n=w.querySelector('#bbh-n'), soort=w.querySelector('#bbh-soort'), go=w.querySelector('.bbh__go'), lbl=w.querySelector('.bbh__go-lbl'), err=w.querySelector('.bbh__err'), rng=w.querySelector('.bbh__range'), res=w.querySelector('.bbh__res');
const Z=[{n:'Ketelhuis',max:650,p:4950,s:'Hoge kap, eigen bar, podium 8 x 6 m'},{n:'Wagenhal',max:280,p:2450,s:'Daglicht, aan het water, eigen terras'},{n:'Seinhuis',max:60,p:875,s:'Vergaderzaal met scherm en geluid'}];
const BUSY={'2026-11-14':['Ketelhuis'],'2026-11-21':['Ketelhuis','Wagenhal'],'2026-12-12':['Ketelhuis','Wagenhal'],'2026-12-19':['Ketelhuis','Wagenhal','Seinhuis']};
const d=s=>new Date(s+'T12:00');
const fmt=x=>x.toLocaleDateString('nl-NL',{weekday:'short',day:'numeric',month:'short'});
const eur=v=>'€ '+v.toLocaleString('nl-NL',{minimumFractionDigits:2,maximumFractionDigits:2});
const days=()=>Math.round((d(tot.value)-d(van.value))/864e5)+1;
const showRange=()=>{if(!van.value||!tot.value||d(tot.value)<d(van.value)){rng.textContent='';return;} const k=days(); rng.textContent=(k===1?fmt(d(van.value)):fmt(d(van.value))+' t/m '+fmt(d(tot.value)))+' · '+k+(k===1?' dag':' dagen')+' · '+n.value+' gasten';};
const clamp=()=>{let v=parseInt(n.value,10); if(isNaN(v)) v=10; n.value=Math.max(10,Math.min(2000,v));};
w.querySelectorAll('.bbh__sb').forEach(b=>b.addEventListener('click',()=>{n.value=(parseInt(n.value,10)||0)+parseInt(b.dataset.d,10); clamp(); showRange();}));
van.addEventListener('change',()=>{if(van.value&&(!tot.value||d(tot.value)<d(van.value))) tot.value=van.value; tot.min=van.value||tot.min; showRange();});
[tot,n].forEach(x=>x.addEventListener('change',()=>{clamp(); showRange();}));
const setErr=(m,el)=>{err.textContent=m; [van,tot].forEach(x=>x.removeAttribute('aria-invalid')); if(el){el.setAttribute('aria-invalid','true'); el.focus();}};
f.addEventListener('submit',e=>{e.preventDefault(); if(go.getAttribute('aria-busy')==='true') return;
if(!van.value||!tot.value){setErr('Kies een begin- en einddatum.',!van.value?van:tot); return;}
if(d(tot.value)<d(van.value)){setErr('De einddatum ligt vóór de begindatum. Kies een datum vanaf '+fmt(d(van.value))+'.',tot); return;}
setErr(''); clamp(); showRange();
go.setAttribute('aria-busy','true'); lbl.textContent='Zoeken...'; res.innerHTML='';
setTimeout(()=>{go.removeAttribute('aria-busy'); lbl.textContent='Bekijk vrije zalen';
const g=+n.value, k=days(), dates=[]; for(let i=0;i<k;i++){const x=d(van.value); x.setDate(x.getDate()+i); dates.push(x.toISOString().slice(0,10));}
const busy=new Set(dates.flatMap(x=>BUSY[x]||[]));
const fit=Z.filter(z=>z.max>=g);
if(!fit.length){res.innerHTML='<p class="bbh__msg"><b>Geen zaal voor '+g+' gasten.</b> Onze grootste zaal, het Ketelhuis, past tot 650 gasten. Voor grotere evenementen gebruiken we ook het buitenterrein: bel Sanne de Wit op 075 123 45 67.</p>'; return;}
res.innerHTML=fit.map(z=>busy.has(z.n)?'<div class="bbh__room bbh__room--off"><b>'+z.n+'</b><span>Al geboekt op deze datum</span><span>Tot '+z.max+' gasten</span></div>':'<div class="bbh__room"><b>'+z.n+'</b><span>'+z.s+'</span><span>Tot '+z.max+' gasten · '+soort.value.toLowerCase()+'</span><strong>vanaf '+eur(z.p*k)+'</strong><button type="button" class="bbh__opt" aria-pressed="false">Optie nemen</button></div>').join('');
if(fit.every(z=>busy.has(z.n))) res.insertAdjacentHTML('beforeend','<p class="bbh__msg">Alle passende zalen zijn bezet. Probeer de vrijdag ervoor of zet u op de wachtlijst.</p>');
},850);
});
res.addEventListener('click',e=>{const b=e.target.closest('.bbh__opt'); if(!b) return; const on=b.getAttribute('aria-pressed')!=='true'; b.setAttribute('aria-pressed',on?'true':'false'); b.textContent=on?'Optie genomen, 7 dagen geldig':'Optie nemen';});
showRange();
}
init(document.querySelector('.jouw-container'));
More page sections
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 →