Fade Modal
A copy-paste modals & overlays component in pure HTML, CSS & vanilla JS. Zero dependencies, framework-agnostic, MIT-licensed.
Modals & OverlaysHTMLCSSJavaScriptany framework
Copy into your project
HTML
<!-- Backdrop -->
<div class="nuda-modal-backdrop" id="modal-backdrop">
<!-- Modal -->
<div class="nuda-modal" role="dialog" aria-modal="true" aria-labelledby="modal-title">
<button class="nuda-modal__close" aria-label="Close">×</button>
<h2 id="modal-title" class="nuda-modal__title">Modal Title</h2>
<p class="nuda-modal__body">Your content goes here.</p>
<div class="nuda-modal__actions">
<button class="nuda-modal__btn nuda-modal__btn--secondary">Cancel</button>
<button class="nuda-modal__btn nuda-modal__btn--primary">Confirm</button>
</div>
</div>
</div>CSS
/* Fade Modal
Modal with fade + scale animation.
Customize: --modal-bg, --modal-accent */
.nuda-modal-backdrop {
position: fixed;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(4px);
z-index: 9999;
opacity: 0;
visibility: hidden;
transition: opacity 0.3s ease, visibility 0.3s ease;
}
.nuda-modal-backdrop.is-open {
opacity: 1;
visibility: visible;
}
.nuda-modal {
--modal-bg: #141414;
--modal-accent: #e4ff54;
position: relative;
background: var(--modal-bg);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
padding: 2rem;
max-width: 420px;
width: 90%;
transform: scale(0.95);
transition: transform 0.3s ease;
}
.nuda-modal-backdrop.is-open .nuda-modal {
transform: scale(1);
}
.nuda-modal__close {
position: absolute;
top: 1rem;
right: 1rem;
background: none;
border: none;
color: #666;
font-size: 1.25rem;
cursor: pointer;
transition: color 0.2s;
}
.nuda-modal__close:hover { color: #fff; }
.nuda-modal__title {
font-size: 1.1rem;
font-weight: 700;
color: #fff;
margin: 0 0 0.5rem;
}
.nuda-modal__body {
font-size: 0.85rem;
color: #999;
margin: 0 0 1.5rem;
}
.nuda-modal__actions {
display: flex;
gap: 0.75rem;
justify-content: flex-end;
}
.nuda-modal__btn {
padding: 0.5rem 1.25rem;
border-radius: 8px;
font-size: 0.8rem;
font-weight: 600;
border: none;
cursor: pointer;
transition: background 0.2s, transform 0.1s;
}
.nuda-modal__btn:active { transform: scale(0.97); }
.nuda-modal__btn--secondary {
background: rgba(255, 255, 255, 0.06);
color: #ccc;
}
.nuda-modal__btn--primary {
background: var(--modal-accent);
color: #0a0a0a;
}
@media (prefers-reduced-motion: reduce) {
.nuda-modal-backdrop,
.nuda-modal {
transition: none;
}
}JavaScript
/* Fade Modal — Toggle with .is-open class */
(function () {
var backdrop = document.getElementById('modal-backdrop');
if (!backdrop) return;
var closeBtn = backdrop.querySelector('.nuda-modal__close');
var cancelBtn = backdrop.querySelector('.nuda-modal__btn--secondary');
function close() {
backdrop.classList.remove('is-open');
}
if (closeBtn) closeBtn.addEventListener('click', close);
if (cancelBtn) cancelBtn.addEventListener('click', close);
backdrop.addEventListener('click', function (e) {
if (e.target === backdrop) close();
});
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape') close();
});
// To open: backdrop.classList.add('is-open');
})();How to use Fade Modal
Paste the HTML where you need it and the CSS into a global stylesheet (or a <style> tag). Every class is prefixed nuda- so it never collides with Tailwind or your own styles. Tweak the CSS custom properties to match your design system.
Works in React, Vue, Svelte, Astro, Next.js, Nuxt, Laravel Blade, Django, Rails — or a single .html file. No npm install, no build step.