Nieuwsbrief met dubbele bevestiging New
Newsletter sign-up with double opt-in the way GDPR prefers: after signing up it does not say "done" but "confirm your address", with the address shown, a resend button that counts down 30 seconds and a link for a different address. In the demo a preview of the confirmation email opens, and only after that click are you really on the list. With an error for an invalid address and focus on each new step.
Nieuws van de kaasboerderij
Eens per maand: wat er van het land komt, nieuwe kazen en de proeverijen in Haastrecht.
Bevestig je aanmelding
We stuurden een mail naar . Klik op de knop in die mail, pas daarna sturen we de nieuwsbrief.
Kaasboerderij De Wit: klopt dit adres?
Je staat op de lijst
De eerste nieuwsbrief komt donderdag 15 oktober. Tot die tijd: de boerderijwinkel is open van dinsdag tot en met zaterdag.
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.
<!-- Nieuwsbrief met dubbele bevestiging · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="nbo"><div class="nbo__in">
<section class="nbo__v" data-v="form">
<h3 class="nbo__h" tabindex="-1">Nieuws van de kaasboerderij</h3>
<p class="nbo__p">Eens per maand: wat er van het land komt, nieuwe kazen en de proeverijen in Haastrecht.</p>
<form class="nbo__f" novalidate>
<label class="nbo__vh" for="nbo-e">E-mailadres</label>
<div class="nbo__row"><input class="nbo__i" id="nbo-e" type="email" autocomplete="email" placeholder="naam@voorbeeld.nl" aria-describedby="nbo-ee"><button class="nbo__btn" type="submit">Aanmelden</button></div>
<p class="nbo__err" id="nbo-ee"></p>
<p class="nbo__small">Je krijgt eerst een mail om je adres te bevestigen. Afmelden kan onder elke nieuwsbrief.</p>
</form>
</section>
<section class="nbo__v" data-v="wait" hidden>
<h3 class="nbo__h" tabindex="-1">Bevestig je aanmelding</h3>
<p class="nbo__p">We stuurden een mail naar <b class="nbo__addr"></b>. Klik op de knop in die mail, pas daarna sturen we de nieuwsbrief.</p>
<div class="nbo__mail" role="group" aria-label="Voorbeeld van de bevestigingsmail"><p class="nbo__mh">Kaasboerderij De Wit: klopt dit adres?</p><button class="nbo__btn nbo__conf" type="button">Ja, schrijf me in</button></div>
<div class="nbo__acts"><button class="nbo__link nbo__again" type="button">Mail opnieuw sturen</button><button class="nbo__link nbo__other" type="button">Ander e-mailadres</button></div>
<p class="nbo__small nbo__st" aria-live="polite"></p>
</section>
<section class="nbo__v" data-v="ok" hidden>
<h3 class="nbo__h" tabindex="-1">Je staat op de lijst</h3>
<p class="nbo__p">De eerste nieuwsbrief komt donderdag 15 oktober. Tot die tijd: de boerderijwinkel is open van dinsdag tot en met zaterdag.</p>
<button class="nbo__link nbo__reset" type="button">Opnieuw bekijken</button>
</section>
</div></div>
</div>/* Nieuwsbrief met dubbele bevestiging · NedDev · eigen werk. */
.nbo{position:absolute;inset:0;overflow:auto;display:flex;padding:12px;box-sizing:border-box;background:#f4f3f1;font-family:'Switzer',sans-serif;color:#0a0a0a}
.nbo *,.nbo *::before,.nbo *::after{box-sizing:border-box}
.nbo [hidden]{display:none!important}
.nbo__in{margin:auto;width:100%;max-width:390px;background:#fff;border:1px solid rgba(10,10,10,.12);border-radius:8px;padding:16px}
.nbo__v{animation:nbo-in .25s ease}
@keyframes nbo-in{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
.nbo__h{margin:0;font-size:17px;font-weight:700;letter-spacing:-.01em;outline:none}
.nbo__p{margin:4px 0 10px;font-size:13px;line-height:1.45;color:#3a3a3a}
.nbo__p b{color:#0a0a0a;word-break:break-all}
.nbo__row{display:flex;gap:6px}
.nbo__i{flex:1;min-width:0;height:38px;padding:0 10px;font:400 14px 'Switzer',sans-serif;color:#0a0a0a;border:1px solid #8c8c8c;border-radius:4px;transition:border-color .15s,box-shadow .15s}
.nbo__i:hover{border-color:#0a0a0a}
.nbo__i:focus-visible{outline:none;border-color:#0a0a0a;box-shadow:0 0 0 3px rgba(245,72,15,.35)}
.nbo__i[aria-invalid="true"]{border-color:#B42318}
.nbo__btn{flex:none;height:38px;padding:0 14px;border:0;border-radius:4px;background:#0a0a0a;color:#fff;font:600 13.5px 'Switzer',sans-serif;cursor:pointer;transition:background-color .15s}
.nbo__btn:hover{background:#2a2a2a}
.nbo__btn:active{transform:translateY(1px)}
.nbo__err{margin:5px 0 0;font-size:12.5px;color:#B42318}
.nbo__err:empty{display:none}
.nbo__small{margin:6px 0 0;font-size:12px;line-height:1.4;color:#4a4a4a}
.nbo__small:empty{display:none}
.nbo__mail{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;padding:9px 10px;margin-bottom:8px;background:#f4f3f1;border-left:3px solid #F5480F;border-radius:0 4px 4px 0}
.nbo__mh{margin:0;font-size:12.5px;font-weight:600}
.nbo__conf{height:32px;font-size:13px;background:#F5480F;color:#0a0a0a}
.nbo__conf:hover{background:#ff6a36}
.nbo__acts{display:flex;gap:16px;flex-wrap:wrap}
.nbo__link{border:0;background:none;padding:4px 0;min-height:24px;font:500 13px 'Switzer',sans-serif;color:#0a0a0a;text-decoration:underline;text-underline-offset:3px;cursor:pointer}
.nbo__link:disabled{color:#6b6b6b;text-decoration:none;cursor:default}
.nbo__vh{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.nbo__btn:focus-visible,.nbo__link:focus-visible{outline:2px solid #F5480F;outline-offset:2px}
.nbo__conf:focus-visible{outline-color:#0a0a0a}
@media (prefers-reduced-motion:reduce){.nbo *{transition:none!important;animation:none!important}}// Nieuwsbrief met dubbele bevestiging · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
var w=root.querySelector('.nbo');if(!w)return;
var sfx='-'+Math.random().toString(36).slice(2,7);
w.querySelectorAll('[id]').forEach(function(el){el.id=el.id+sfx;});
w.querySelectorAll('[for]').forEach(function(el){el.setAttribute('for',el.getAttribute('for')+sfx);});
w.querySelectorAll('[aria-describedby]').forEach(function(el){el.setAttribute('aria-describedby',el.getAttribute('aria-describedby')+sfx);});
var views=w.querySelectorAll('.nbo__v'),e=w.querySelector('.nbo__i'),ee=w.querySelector('.nbo__err'),again=w.querySelector('.nbo__again'),st=w.querySelector('.nbo__st'),cd=null;
var RE=/^[^\s@]+@[^\s@]+\.[a-z]{2,}$/i;
function show(v){views.forEach(function(s){s.hidden=s.getAttribute('data-v')!==v;});w.querySelector('[data-v="'+v+'"] .nbo__h').focus();}
function count(){var n=30;clearInterval(cd);again.disabled=true;again.textContent='Opnieuw sturen kan over '+n+' s';
cd=setInterval(function(){n--;if(n<=0){clearInterval(cd);again.disabled=false;again.textContent='Mail opnieuw sturen';return;}again.textContent='Opnieuw sturen kan over '+n+' s';},1000);}
w.querySelector('.nbo__f').addEventListener('submit',function(ev){ev.preventDefault();var v=e.value.trim(),m=!v?'Vul je e-mailadres in':!RE.test(v)?'Controleer je e-mailadres, er lijkt iets te missen':'';
ee.textContent=m;if(m){e.setAttribute('aria-invalid','true');e.focus();return;}e.removeAttribute('aria-invalid');
w.querySelector('.nbo__addr').textContent=v;st.textContent='';show('wait');count();});
e.addEventListener('input',function(){if(e.getAttribute('aria-invalid')&&RE.test(e.value.trim())){e.removeAttribute('aria-invalid');ee.textContent='';}});
again.addEventListener('click',function(){st.textContent='Verstuurd. Kijk ook in je map met ongewenste mail.';count();});
w.querySelector('.nbo__other').addEventListener('click',function(){clearInterval(cd);show('form');e.focus();e.select();});
w.querySelector('.nbo__conf').addEventListener('click',function(){clearInterval(cd);show('ok');});
w.querySelector('.nbo__reset').addEventListener('click',function(){e.value='';again.disabled=false;again.textContent='Mail opnieuw sturen';show('form');});
}
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 →