Bottom Sheet
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
<div class="nuda-bsheet-backdrop" id="bottom-sheet">
<div class="nuda-bsheet" role="dialog" aria-label="Bottom sheet">
<div class="nuda-bsheet__handle"></div>
<h3 class="nuda-bsheet__title">Title</h3>
<p class="nuda-bsheet__body">Sheet content goes here.</p>
</div>
</div>CSS
/* Bottom Sheet
Mobile-style bottom sheet that slides up.
Customize: --sheet-bg, --sheet-handle */
.nuda-bsheet-backdrop {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 9999;
opacity: 0;
visibility: hidden;
transition: opacity 0.3s ease, visibility 0.3s ease;
}
.nuda-bsheet-backdrop.is-open {
opacity: 1;
visibility: visible;
}
.nuda-bsheet {
--sheet-bg: #141414;
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: var(--sheet-bg);
border-top: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 16px 16px 0 0;
padding: 1rem 1.5rem 2rem;
max-height: 80vh;
overflow-y: auto;
transform: translateY(100%);
transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
.nuda-bsheet-backdrop.is-open .nuda-bsheet {
transform: translateY(0);
}
.nuda-bsheet__handle {
width: 36px;
height: 4px;
background: rgba(255, 255, 255, 0.2);
border-radius: 2px;
margin: 0 auto 1rem;
}
.nuda-bsheet__title {
font-size: 1rem;
font-weight: 700;
color: #fff;
margin: 0 0 0.5rem;
}
.nuda-bsheet__body {
font-size: 0.85rem;
color: #999;
}
@media (prefers-reduced-motion: reduce) {
.nuda-bsheet-backdrop,
.nuda-bsheet {
transition: none;
}
}JavaScript
/* Bottom Sheet — Toggle with .is-open class */
(function () {
var backdrop = document.getElementById('bottom-sheet');
if (!backdrop) return;
function close() {
backdrop.classList.remove('is-open');
}
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 Bottom Sheet
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.