Aandacht vragen, ingetogen Nieuw
Drie rustige manieren om aandacht te vragen, elk met een variant voor minder beweging: een knop die na 4 seconden stilstand één keer zacht pulseert (daarna niet meer), een veld dat kort wiebelt bij een fout na versturen (met foutmelding via aria-live), en een tellerbadge die even opveert bij toevoegen. Wel: één keer, als reactie op de bezoeker. Niet: herhalen, op meerdere knoppen tegelijk of als nep-urgentie. Gewone CSS-keyframes; tabs met pijltjestoetsen.
Na 4 seconden stilstand pulseert de knop één keer. Wel bij één hoofdactie, niet herhalen.
Wacht op stilstand.
Alleen na versturen, nooit tijdens het typen. De tekst legt uit wat er mis is.
Een bevestiging van wat de bezoeker net deed, geen nep-urgentie.
Zo gebruik je het
- Plak de HTML op de plek waar het onderdeel moet komen.
- Zet de CSS in je stylesheet. Alle klassen hebben een eigen voorvoegsel, dus niets botst met je eigen opmaak.
- Voeg de JavaScript toe en roep init() aan met het element waar de HTML in staat.
<!-- Aandacht vragen, ingetogen · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="atr">
<div class="atr__tabs" role="tablist" aria-label="Soorten aandacht">
<button class="atr__tab" type="button" role="tab" id="atr-t1" aria-controls="atr-p1" aria-selected="true">Zachte puls</button>
<button class="atr__tab" type="button" role="tab" id="atr-t2" aria-controls="atr-p2" aria-selected="false" tabindex="-1">Wiebel bij fout</button>
<button class="atr__tab" type="button" role="tab" id="atr-t3" aria-controls="atr-p3" aria-selected="false" tabindex="-1">Teller</button>
</div>
<div class="atr__panel" role="tabpanel" id="atr-p1" aria-labelledby="atr-t1">
<p class="atr__note">Na 4 seconden stilstand pulseert de knop één keer. Wel bij één hoofdactie, niet herhalen.</p>
<div class="atr__row"><button class="atr__cta atr__puls" type="button">Plan een adviesgesprek</button><button class="atr__link atr__reset" type="button">Opnieuw</button></div>
<p class="atr__st" aria-live="polite">Wacht op stilstand.</p>
</div>
<div class="atr__panel" role="tabpanel" id="atr-p2" aria-labelledby="atr-t2" hidden>
<p class="atr__note">Alleen na versturen, nooit tijdens het typen. De tekst legt uit wat er mis is.</p>
<form class="atr__form" novalidate><label class="atr__lab" for="atr-pc">Postcode</label><div class="atr__row"><input class="atr__in" id="atr-pc" type="text" inputmode="text" autocomplete="postal-code" placeholder="3511 AB" aria-describedby="atr-msg"><button class="atr__cta" type="submit">Controleer</button></div>
<p class="atr__msg" id="atr-msg" aria-live="polite"></p></form>
</div>
<div class="atr__panel" role="tabpanel" id="atr-p3" aria-labelledby="atr-t3" hidden>
<p class="atr__note">Een bevestiging van wat de bezoeker net deed, geen nep-urgentie.</p>
<div class="atr__row"><span class="atr__prod">Fietsbel, messing <b>€ 14,95</b></span><button class="atr__cta atr__add" type="button">In winkelmand</button>
<a class="atr__cart" href="#aandachtstrekker-set" aria-label="Winkelmand, leeg"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M2 3h2.5l2 10h9l1.8-7H6"/><circle cx="8" cy="16.5" r="1.2"/><circle cx="14.5" cy="16.5" r="1.2"/></svg><span class="atr__badge" hidden>0</span></a><button class="atr__link atr__empty" type="button">Leegmaken</button></div>
<p class="atr__st atr__cst" aria-live="polite"></p>
</div>
</div>
</div>/* Aandacht vragen, ingetogen · NedDev · eigen werk. */
.atr{position:absolute;inset:0;display:flex;flex-direction:column;background:#fff;color:#0a0a0a;font-family:'Switzer',sans-serif;padding:12px 16px;box-sizing:border-box;text-align:left;overflow:auto;scrollbar-width:thin}
.atr *,.atr *::before,.atr *::after{box-sizing:border-box}
.atr__tabs{flex:none;display:flex;gap:16px;border-bottom:1px solid #e4e2de;margin-bottom:12px}
.atr__tab{position:relative;margin:0;padding:6px 0 9px;border:0;background:none;color:#5c5a57;font:500 13px/1.2 'Switzer',sans-serif;cursor:pointer;transition:color .16s}
.atr__tab:hover{color:#0a0a0a}
.atr__tab[aria-selected="true"]{color:#0a0a0a;font-weight:600}
.atr__tab[aria-selected="true"]::after{content:'';position:absolute;left:0;right:0;bottom:-1px;height:2px;background:#F5480F}
.atr__tab:focus-visible{outline:2px solid #F5480F;outline-offset:2px;border-radius:4px}
.atr__panel{flex:1 0 auto;display:flex;flex-direction:column;justify-content:center;gap:10px;padding-bottom:12px}
.atr__panel[hidden]{display:none}
.atr__note{margin:0;font:400 13px/1.45 'Switzer',sans-serif;color:#4a4845;max-width:34em}
.atr__row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.atr__cta{position:relative;margin:0;padding:10px 14px;border:0;border-radius:4px;background:#0a0a0a;color:#fff;font:600 13px/1 'Switzer',sans-serif;cursor:pointer;transition:background-color .16s}
.atr__cta:hover{background:#333}
.atr__cta:active{transform:translateY(1px)}
.atr__cta:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.atr__puls{background:#F5480F;color:#0a0a0a}
.atr__puls:hover{background:#ff6a36}
.atr__puls::after{content:'';position:absolute;inset:0;border-radius:4px;border:2px solid #F5480F;opacity:0;pointer-events:none}
.atr__link{margin:0;padding:4px 2px;border:0;background:none;color:#0a0a0a;font:500 13px/1.2 'Switzer',sans-serif;text-decoration:underline;text-underline-offset:3px;cursor:pointer}
.atr__link:hover{color:#b8330a}
.atr__link:focus-visible{outline:2px solid #F5480F;outline-offset:2px;border-radius:4px}
.atr__st{margin:0;font:400 12px/1.3 'Switzer',sans-serif;color:#5c5a57;min-height:1.3em}
.atr__lab{display:block;margin-bottom:4px;font:500 13px/1.2 'Switzer',sans-serif}
.atr__in{width:120px;height:36px;margin:0;padding:0 10px;border:1px solid #8a8781;border-radius:4px;font:400 14px 'Switzer',sans-serif;color:#0a0a0a;background:#fff;transition:border-color .16s}
.atr__in:hover{border-color:#0a0a0a}
.atr__in:focus-visible{outline:2px solid #F5480F;outline-offset:1px;border-color:#0a0a0a}
.atr__in[aria-invalid="true"]{border-color:#c4231b;border-width:2px}
.atr__msg{margin:6px 0 0;min-height:1.3em;font:500 12.5px/1.3 'Switzer',sans-serif}
.atr__msg.is-fout{color:#c4231b}
.atr__msg.is-ok{color:#17663a}
.atr__msg.is-fout::before{content:'! ';font-weight:700}
.atr__prod{font:400 13px/1.3 'Switzer',sans-serif}
.atr__prod b{font-weight:600;margin-left:4px}
.atr__cart{position:relative;display:grid;place-items:center;width:36px;height:36px;border:1px solid #cfccc7;border-radius:4px;color:#0a0a0a;transition:border-color .16s}
.atr__cart:hover{border-color:#0a0a0a}
.atr__cart:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.atr__cart svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.6;stroke-linejoin:round;stroke-linecap:round}
.atr__badge{position:absolute;top:-7px;right:-7px;min-width:18px;height:18px;padding:0 4px;border-radius:4px;background:#F5480F;color:#0a0a0a;font:700 11px/18px 'Switzer',sans-serif;text-align:center;font-variant-numeric:tabular-nums}
.atr__badge[hidden]{display:none}
@media (prefers-reduced-motion:no-preference){
.atr__puls.is-puls::after{animation:atr-puls 1.4s cubic-bezier(.2,.6,.3,1) 2}
.atr__in.is-wiebel{animation:atr-wiebel .36s ease-in-out}
.atr__badge.is-op{animation:atr-op .26s cubic-bezier(.3,.7,.3,1.4)}}
@media (prefers-reduced-motion:reduce){.atr__puls.is-puls::after{opacity:1;inset:-4px;border-radius:4px}}
@keyframes atr-puls{0%{opacity:.8;inset:0}100%{opacity:0;inset:-9px}}
@keyframes atr-wiebel{0%,100%{transform:none}20%{transform:translateX(-5px)}40%{transform:translateX(5px)}60%{transform:translateX(-3px)}80%{transform:translateX(2px)}}
@keyframes atr-op{0%{transform:scale(1)}50%{transform:scale(1.28)}100%{transform:scale(1)}}// Aandacht vragen, ingetogen · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
var w=root.querySelector('.atr');if(!w)return;
var tabs=[].slice.call(w.querySelectorAll('.atr__tab'));
function sel(t,f){tabs.forEach(function(x){var on=x===t;x.setAttribute('aria-selected',on);x.tabIndex=on?0:-1;w.querySelector('#'+x.getAttribute('aria-controls')).hidden=!on;});if(f)t.focus();if(t.id==='atr-t1')arm();}
tabs.forEach(function(t,k){t.addEventListener('click',function(){sel(t);});t.addEventListener('keydown',function(e){var j=null;if(e.key==='ArrowRight')j=(k+1)%tabs.length;else if(e.key==='ArrowLeft')j=(k-1+tabs.length)%tabs.length;else if(e.key==='Home')j=0;else if(e.key==='End')j=tabs.length-1;if(j!==null){e.preventDefault();sel(tabs[j],true);}});});
var puls=w.querySelector('.atr__puls'),st=w.querySelector('#atr-p1 .atr__st'),idle=null,done=false;
function arm(){clearTimeout(idle);if(done)return;st.textContent='Wacht op stilstand.';idle=setTimeout(function(){if(w.querySelector('#atr-p1').hidden)return;puls.classList.add('is-puls');done=true;st.textContent='Eén keer gepulseerd, daarna niet meer.';},4000);}
['pointermove','keydown','wheel'].forEach(function(ev){w.addEventListener(ev,function(){if(!done)arm();},{passive:true});});
puls.addEventListener('click',function(){puls.classList.remove('is-puls');clearTimeout(idle);done=true;st.textContent='Gekozen. De knop vraagt geen aandacht meer.';});
w.querySelector('.atr__reset').addEventListener('click',function(){puls.classList.remove('is-puls');done=false;arm();});
var form=w.querySelector('.atr__form'),inp=w.querySelector('.atr__in'),msg=w.querySelector('.atr__msg');
form.addEventListener('submit',function(e){e.preventDefault();var v=inp.value.trim().toUpperCase();var ok=/^[1-9][0-9]{3} ?[A-Z]{2}$/.test(v);msg.className='atr__msg';
if(ok){inp.removeAttribute('aria-invalid');msg.classList.add('is-ok');msg.textContent='Klopt, we bezorgen in '+v.replace(/^(\d{4}) ?/,'$1 ')+'.';return;}
inp.setAttribute('aria-invalid','true');msg.classList.add('is-fout');msg.textContent=v?'Een postcode heeft 4 cijfers en 2 letters, zoals 3511 AB.':'Vul je postcode in.';
inp.classList.remove('is-wiebel');void inp.offsetWidth;inp.classList.add('is-wiebel');inp.focus();});
inp.addEventListener('animationend',function(){inp.classList.remove('is-wiebel');});
var n=0,badge=w.querySelector('.atr__badge'),cart=w.querySelector('.atr__cart'),cst=w.querySelector('.atr__cst');
function setN(k){n=k;badge.hidden=n===0;badge.textContent=n;cart.setAttribute('aria-label',n?'Winkelmand, '+n+(n===1?' artikel':' artikelen'):'Winkelmand, leeg');cst.textContent=n?n+(n===1?' artikel':' artikelen')+' in je winkelmand.':'Je winkelmand is leeg.';}
w.querySelector('.atr__add').addEventListener('click',function(){setN(n+1);badge.classList.remove('is-op');void badge.offsetWidth;badge.classList.add('is-op');});
w.querySelector('.atr__empty').addEventListener('click',function(){setN(0);});
cart.addEventListener('click',function(e){e.preventDefault();});
arm();
}
init(document.querySelector('.jouw-container'));
Meer uit knoppen
Iets gezien dat je mooi vindt?
Zet het in je selectie en stuur hem op. Dan bouwen we je site eromheen, in jouw huisstijl.
Neem contact op →