Inline meldingen (info, succes, let op, fout) New
Four inline alerts with icon, word label and text, so meaning never relies on colour alone. Each is dismissible (smooth collapse via grid rows, focus moves on sensibly) and has an action button with loading and end state; the error turns into a success after "Try again". role="alert" for errors, role="status" for the rest, plus an empty state. A container query moves the action below the text in narrow columns.
Info: van do 24 dec t/m vr 1 jan is de praktijk gesloten.
OpeningstijdenGelukt: je afspraak staat op wo 14 okt om 09:30.
Let op: je iDEAL-betaling van € 64,95 staat nog open.
Fout: we konden postcode 3481 AB niet controleren.
Geen meldingen meer.
How to use it
- Paste the HTML where the components 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.
<!-- Inline meldingen (info, succes, let op, fout) · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="als" role="region" aria-label="Meldingen">
<div class="als__a als__a--info" role="status"><div class="als__in">
<svg class="als__i" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5M12 8h.01"/></svg>
<p class="als__p"><strong>Info:</strong> van do 24 dec t/m vr 1 jan is de praktijk gesloten.</p>
<a class="als__act" href="#openingstijden">Openingstijden</a>
<button class="als__x" type="button" aria-label="Sluit melding: praktijk gesloten"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6 6l12 12M18 6 6 18"/></svg></button></div></div>
<div class="als__a als__a--ok" role="status"><div class="als__in">
<svg class="als__i" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="m8 12 3 3 5-6"/></svg>
<p class="als__p"><strong>Gelukt:</strong> je afspraak staat op wo 14 okt om 09:30.</p>
<button class="als__act" type="button" data-busy="Toevoegen" data-done="In agenda gezet">Zet in agenda</button>
<button class="als__x" type="button" aria-label="Sluit melding: afspraak bevestigd"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6 6l12 12M18 6 6 18"/></svg></button></div></div>
<div class="als__a als__a--warn" role="status"><div class="als__in">
<svg class="als__i" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5 2.5 20h19z"/><path d="M12 10v4M12 17h.01"/></svg>
<p class="als__p"><strong>Let op:</strong> je iDEAL-betaling van € 64,95 staat nog open.</p>
<button class="als__act" type="button" data-busy="Openen" data-done="Naar je bank">Nu betalen</button>
<button class="als__x" type="button" aria-label="Sluit melding: betaling open"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6 6l12 12M18 6 6 18"/></svg></button></div></div>
<div class="als__a als__a--err" role="alert"><div class="als__in">
<svg class="als__i" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M9 9l6 6M15 9l-6 6"/></svg>
<p class="als__p"><strong>Fout:</strong> we konden postcode 3481 AB niet controleren.</p>
<button class="als__act als__retry" type="button">Opnieuw proberen</button>
<button class="als__x" type="button" aria-label="Sluit melding: adrescontrole mislukt"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6 6l12 12M18 6 6 18"/></svg></button></div></div>
<div class="als__empty"><p>Geen meldingen meer.</p><button class="als__reset" type="button">Toon de voorbeelden opnieuw</button></div>
</div>
</div>/* Inline meldingen (info, succes, let op, fout) · NedDev · eigen werk. */
.als{--ink:#0a0a0a;--pd:#b83a0b;position:absolute;inset:0;overflow:auto;padding:12px 14px;display:flex;flex-direction:column;justify-content:safe center;font-family:'Switzer',system-ui,sans-serif;color:var(--ink);container-type:inline-size}
.als__a{display:grid;grid-template-rows:1fr;opacity:1;margin-bottom:7px;transition:grid-template-rows .28s ease,opacity .2s ease,margin .28s ease}
.als__a.is-gone{grid-template-rows:0fr;opacity:0;margin-bottom:0}
.als__a[hidden]{display:none}
.als__in{min-height:0;overflow:hidden;display:grid;grid-template-columns:18px 1fr auto 28px;align-items:center;gap:8px;padding:7px 6px 7px 10px;border:1px solid;border-left-width:4px;border-radius:4px;background:var(--bg);border-color:var(--bd);border-left-color:var(--c)}
.als__a--info{--c:#1e4fa8;--bg:#eef3fb;--bd:#c9d8f1}
.als__a--ok{--c:#14713d;--bg:#ebf6ef;--bd:#c3e3cf}
.als__a--warn{--c:#8a5300;--bg:#fff5dc;--bd:#f0d79a}
.als__a--err{--c:#b3261e;--bg:#fdeeed;--bd:#f2c4c0}
.als__i{width:18px;height:18px;fill:none;stroke:var(--c);stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.als__p{margin:0;font-size:12.5px;line-height:1.35}
.als__p strong{color:var(--c)}
.als__act{font:600 11.5px/1 'Switzer',system-ui,sans-serif;padding:7px 9px;border-radius:4px;border:1px solid var(--c);background:#fff;color:var(--c);cursor:pointer;text-decoration:none;white-space:nowrap;display:inline-flex;align-items:center;gap:6px;transition:background .15s,color .15s}
.als__act:hover{background:var(--c);color:#fff}
.als__act:active{transform:translateY(1px)}
.als__act[aria-busy=true]{cursor:progress;opacity:.8}
.als__act[aria-busy=true]::before{content:'';width:10px;height:10px;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:als-spin .7s linear infinite}
.als__act:disabled{cursor:default;background:#fff;color:var(--c);opacity:.75}
@keyframes als-spin{to{transform:rotate(360deg)}}
.als__x{grid-column:4;width:28px;height:28px;border:0;border-radius:4px;background:none;cursor:pointer;display:grid;place-items:center;color:var(--ink);padding:0}
.als__x:hover{background:rgba(10,10,10,.07)}
.als__x svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}
.als button:focus-visible,.als a:focus-visible{outline:2px solid var(--pd);outline-offset:2px}
.als__empty{display:none;flex-direction:column;align-items:center;gap:10px;text-align:center;font-size:13px;color:#5b5b5b}
.als__empty p{margin:0}
.als.is-empty .als__empty{display:flex}
.als__reset{font:600 12px/1 'Switzer',system-ui,sans-serif;padding:9px 12px;border:1px solid var(--ink);border-radius:4px;background:#fff;color:var(--ink);cursor:pointer}
.als__reset:hover{background:var(--ink);color:#fff}
@container (max-width:380px){.als__in{grid-template-columns:18px 1fr 28px;row-gap:5px}.als__i{align-self:start;margin-top:1px}.als__x{grid-column:3;grid-row:1;align-self:start}.als__act{grid-column:2;grid-row:2;justify-self:start;padding:5px 8px}.als__p{font-size:12px}}
@media (prefers-reduced-motion:reduce){.als__a{transition:none}}// Inline meldingen (info, succes, let op, fout) · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
var w=root.querySelector('.als');if(!w)return;var reduce=matchMedia('(prefers-reduced-motion: reduce)').matches;
var orig=w.innerHTML;
function bind(){
w.querySelectorAll('.als__x').forEach(function(x){x.addEventListener('click',function(){var a=x.closest('.als__a');var all=[].slice.call(w.querySelectorAll('.als__a:not(.is-gone)'));var i=all.indexOf(a);a.classList.add('is-gone');
var nxt=all[i+1]||all[i-1];setTimeout(function(){a.hidden=true;if(!w.querySelector('.als__a:not([hidden])')){w.classList.add('is-empty');w.querySelector('.als__reset').focus();}},reduce?0:280);
if(nxt)nxt.querySelector('.als__x').focus();});});
w.querySelectorAll('.als__act[data-busy]').forEach(function(b){var t0=b.textContent;b.addEventListener('click',function(){b.setAttribute('aria-busy','true');b.textContent=b.dataset.busy;
setTimeout(function(){b.removeAttribute('aria-busy');b.textContent=b.dataset.done;b.disabled=true;},900);});});
var r=w.querySelector('.als__retry');if(r)r.addEventListener('click',function(){r.setAttribute('aria-busy','true');r.textContent='Controleren';
setTimeout(function(){var a=r.closest('.als__a');a.className='als__a als__a--ok';a.setAttribute('role','status');
a.querySelector('.als__i').innerHTML='<circle cx="12" cy="12" r="9"/><path d="m8 12 3 3 5-6"/>';
a.querySelector('.als__p').innerHTML='<strong>Gelukt:</strong> adres gevonden, Dorpsstraat 12, 3481 AB Harmelen.';
a.querySelector('.als__x').setAttribute('aria-label','Sluit melding: adres gevonden');r.remove();a.querySelector('.als__x').focus();},1100);});
var rs=w.querySelector('.als__reset');rs.addEventListener('click',function(){w.classList.remove('is-empty');w.innerHTML=orig;bind();var f=w.querySelector('.als__x');if(f)f.focus();});}
bind();
}
init(document.querySelector('.jouw-container'));
More components
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 →