Contactknop die uitklapt New
Floating contact button that expands to Call, WhatsApp, Mail and Directions, each with a readable label. Works with Enter, Space, arrows and Esc (focus returns), closes on outside click and sets aria-expanded. Plain links (tel:, wa.me, mailto:, maps), so usable without JS; remove the data-demo attribute in production.
24/7 storingsdienst · Utrecht e.o.
Lekkage of geen warm water?
Loodgietersbedrijf Van Dijk is gemiddeld binnen 45 minuten bij je. Voorrijden binnen de ring: € 45.
How to use it
- Paste the HTML where the buttons 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.
<!-- Contactknop die uitklapt · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="sdc" data-demo>
<div class="sdc__page"><p class="sdc__kicker">24/7 storingsdienst · Utrecht e.o.</p><p class="sdc__h">Lekkage of geen warm water?</p><p class="sdc__p">Loodgietersbedrijf Van Dijk is gemiddeld binnen 45 minuten bij je. Voorrijden binnen de ring: € 45.</p></div>
<div class="sdc__dial">
<ul class="sdc__list">
<li class="sdc__item" style="--i:0"><a class="sdc__act" href="tel:+31301234567"><span class="sdc__lbl">Bellen<small>nu bereikbaar</small></span><span class="sdc__ico"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M6.6 3.2l2 3.1-1.4 1.6a9 9 0 0 0 4.9 4.9l1.6-1.4 3.1 2-.7 2.6c-.2.6-.8 1-1.4.9C8.3 16.3 3.7 11.7 3.1 5.3c0-.6.3-1.2.9-1.4z"/></svg></span></a></li>
<li class="sdc__item" style="--i:1"><a class="sdc__act" href="https://wa.me/31612345678?text=Hallo%20Van%20Dijk"><span class="sdc__lbl">WhatsApp<small>antwoord binnen 10 min</small></span><span class="sdc__ico sdc__ico--wa"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M10 2.8a7.2 7.2 0 0 0-6.2 10.9L3 17l3.4-.8A7.2 7.2 0 1 0 10 2.8z"/><path d="M7.6 7c.2-.4.5-.4.7-.4l.5 1.2-.5.7a5 5 0 0 0 2.3 2.3l.7-.5 1.2.5c0 .3 0 .6-.4.8-.5.3-1.2.4-2-.1A6.6 6.6 0 0 1 7.5 9c-.4-.8-.3-1.5.1-2z"/></svg></span></a></li>
<li class="sdc__item" style="--i:2"><a class="sdc__act" href="mailto:service@voorbeeld.nl"><span class="sdc__lbl">Mail<small>service@voorbeeld.nl</small></span><span class="sdc__ico"><svg viewBox="0 0 20 20" aria-hidden="true"><rect x="2.8" y="4.5" width="14.4" height="11" rx="1.5"/><path d="M3.3 5.2l6.7 5.3 6.7-5.3"/></svg></span></a></li>
<li class="sdc__item" style="--i:3"><a class="sdc__act" href="https://www.google.com/maps/dir/?api=1&destination=Kanaalweg+20+Utrecht"><span class="sdc__lbl">Route<small>Kanaalweg 20, Utrecht</small></span><span class="sdc__ico"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M10 17.5s5.5-5 5.5-9a5.5 5.5 0 0 0-11 0c0 4 5.5 9 5.5 9z"/><circle cx="10" cy="8.5" r="2"/></svg></span></a></li>
</ul>
<button type="button" class="sdc__fab" aria-expanded="false" aria-label="Contact opnemen"><svg class="sdc__chat" viewBox="0 0 24 24" aria-hidden="true"><path d="M4 5h16v11H9l-5 4z"/><path d="M8 9.5h8M8 12.5h5"/></svg><svg class="sdc__x" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg></button>
</div>
<p class="sdc__status" role="status"></p>
</div>
</div>/* Contactknop die uitklapt · NedDev · eigen werk. */
.sdc{position:absolute;inset:0;container-type:size;overflow:hidden;background:#f4f3f1;color:#0a0a0a;font-family:'Switzer',system-ui,sans-serif;text-align:left}
.sdc *,.sdc *::before,.sdc *::after{box-sizing:border-box}
.sdc__page{padding:16px 18px;max-width:300px}
.sdc__kicker{margin:0 0 6px;font:500 10px/1.2 'JetBrains Mono',ui-monospace,monospace;letter-spacing:.08em;text-transform:uppercase;color:#5c5a57}
.sdc__h{margin:0 0 6px;font-size:20px;font-weight:700;line-height:1.15;letter-spacing:-.015em}
.sdc__p{margin:0;font-size:13px;line-height:1.5;color:#3d3b38}
.sdc::after{content:'';position:absolute;inset:0;background:rgba(244,243,241,.82);opacity:0;pointer-events:none;transition:opacity .2s;z-index:1}
.sdc.is-open::after{opacity:1}
.sdc__dial{position:absolute;right:14px;bottom:14px;z-index:2;display:flex;flex-direction:column;align-items:flex-end;gap:10px}
.sdc__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column-reverse;align-items:flex-end;gap:8px}
.sdc__item{opacity:0;visibility:hidden;transform:translateY(8px);transition:opacity .16s ease,transform .16s ease,visibility 0s linear .16s;transition-delay:0s}
.sdc.is-open .sdc__item{opacity:1;visibility:visible;transform:none;transition:opacity .18s ease,transform .18s ease,visibility 0s;transition-delay:calc(var(--i) * 35ms)}
.sdc__act{display:flex;align-items:center;gap:10px;text-decoration:none;color:#0a0a0a;border-radius:999px}
.sdc__lbl{display:flex;flex-direction:column;align-items:flex-end;background:#fff;border:1px solid #e0ddd8;border-radius:4px;padding:5px 9px;font-size:13px;font-weight:600;line-height:1.2;box-shadow:0 4px 12px rgba(10,10,10,.08);transition:border-color .15s}
.sdc__lbl small{font:500 10px/1.2 'JetBrains Mono',ui-monospace,monospace;color:#5c5a57}
.sdc__ico{flex:none;width:38px;height:38px;border-radius:50%;display:grid;place-items:center;background:#fff;border:1px solid #d6d2cc;box-shadow:0 4px 12px rgba(10,10,10,.1);transition:background .15s,border-color .15s}
.sdc__ico svg{width:18px;height:18px;fill:none;stroke:#0a0a0a;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.sdc__ico--wa{background:#0f6e4a;border-color:#0f6e4a}
.sdc__ico--wa svg{stroke:#fff}
.sdc__act:hover .sdc__lbl{border-color:#0a0a0a}
.sdc__act:hover .sdc__ico{border-color:#0a0a0a}
.sdc__act:focus-visible{outline:none}
.sdc__act:focus-visible .sdc__ico{outline:2px solid #F5480F;outline-offset:2px}
.sdc__act:focus-visible .sdc__lbl{border-color:#0a0a0a}
.sdc__fab{position:relative;width:52px;height:52px;border-radius:50%;border:0;background:#F5480F;color:#fff;cursor:pointer;box-shadow:0 8px 20px rgba(245,72,15,.35);display:grid;place-items:center;transition:background .15s,transform .15s}
.sdc__fab:hover{background:#d93d08}
.sdc__fab:active{transform:scale(.95)}
.sdc__fab:focus-visible{outline:2px solid #0a0a0a;outline-offset:3px}
.sdc__fab svg{grid-area:1/1;width:24px;height:24px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;transition:opacity .15s,transform .2s}
.sdc__x{opacity:0;transform:rotate(-45deg)}
.sdc.is-open .sdc__chat{opacity:0;transform:rotate(45deg)}
.sdc.is-open .sdc__x{opacity:1;transform:none}
.sdc.is-open .sdc__fab{background:#0a0a0a;box-shadow:0 8px 20px rgba(10,10,10,.25)}
.sdc__status{position:absolute;left:18px;bottom:16px;right:90px;z-index:3;margin:0;font-size:12px;line-height:1.35;color:#0a0a0a;min-height:16px}
.sdc__status:empty{display:none}
.sdc__status:not(:empty){background:#fff;border:1px solid #e0ddd8;border-radius:4px;padding:6px 8px;max-width:220px}
@container (max-height:236px){.sdc__dial{right:10px;bottom:10px;gap:6px}.sdc__list{gap:4px}.sdc__ico{width:32px;height:32px}.sdc__ico svg{width:16px;height:16px}.sdc__lbl{padding:3px 8px;font-size:12px}.sdc__lbl small{display:none}.sdc__fab{width:46px;height:46px}.sdc__page{padding:12px 14px}.sdc__h{font-size:17px}.sdc__status{left:12px;bottom:12px;right:auto;max-width:140px}}
@media (prefers-reduced-motion:reduce){.sdc__item,.sdc.is-open .sdc__item{transform:none;transition-delay:0s}.sdc__fab svg{transition:opacity .15s}}// Contactknop die uitklapt · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
var w=root.querySelector('.sdc');if(!w)return;
var fab=w.querySelector('.sdc__fab'),list=w.querySelector('.sdc__list'),acts=[].slice.call(w.querySelectorAll('.sdc__act')),status=w.querySelector('.sdc__status'),dial=w.querySelector('.sdc__dial');
list.id='sdc'+Math.random().toString(36).slice(2,8);fab.setAttribute('aria-controls',list.id);list.setAttribute('aria-label','Contactmogelijkheden');
function isOpen(){return w.classList.contains('is-open');}
function open(focusFirst){w.classList.add('is-open');fab.setAttribute('aria-expanded','true');fab.setAttribute('aria-label','Contactopties sluiten');if(focusFirst)setTimeout(function(){acts[0].focus();},30);}
function close(refocus){w.classList.remove('is-open');fab.setAttribute('aria-expanded','false');fab.setAttribute('aria-label','Contact opnemen');if(refocus)fab.focus();}
fab.addEventListener('click',function(e){isOpen()?close(false):open(e.detail===0);});
fab.addEventListener('keydown',function(e){if(e.key==='ArrowUp'){e.preventDefault();open(true);}else if(e.key==='Escape'&&isOpen()){close(true);}});
acts.forEach(function(a,i){a.addEventListener('keydown',function(e){
if(e.key==='ArrowUp'){e.preventDefault();acts[Math.min(acts.length-1,i+1)].focus();}
else if(e.key==='ArrowDown'){e.preventDefault();if(i===0)fab.focus();else acts[i-1].focus();}
else if(e.key==='Escape'){e.preventDefault();close(true);}});
a.addEventListener('click',function(e){if(!w.hasAttribute('data-demo'))return;e.preventDefault();var l=a.querySelector('.sdc__lbl').firstChild.textContent;status.textContent='Demo: "'+l+'" opent '+(l==='Bellen'?'je telefoon met 030 123 4567':l==='WhatsApp'?'een chat met de storingsdienst':l==='Mail'?'je mailprogramma':'de routeplanner')+'.';close(true);});});
document.addEventListener('pointerdown',function(e){if(isOpen()&&!dial.contains(e.target))close(false);});
dial.addEventListener('focusout',function(e){if(isOpen()&&e.relatedTarget&&!dial.contains(e.relatedTarget))close(false);});
}
init(document.querySelector('.jouw-container'));
More buttons
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 →