Bootstrap 5 Offcanvas Full-Screen Navigation Menu
A full-screen hero with a Menu button that slides a large typographic navigation panel in from the left, with links that animate in one after another. Built on the Bootstrap offcanvas, so focus handling and the Escape key work out of the box.
<section class="canvas-hero wdw-aurora">
<header class="position-relative z-2 p-3 p-md-4">
<button class="btn btn-light rounded-pill canvas-menu-btn" type="button" data-bs-toggle="offcanvas" data-bs-target="#canvasNav" aria-controls="canvasNav">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M4 7h16M4 12h10M4 17h16"/></svg>
Menu
</button>
</header>
<div class="canvas-body position-relative z-2 container">
<div class="row align-items-center g-5">
<div class="col-lg-7 text-center text-lg-start">
<span class="canvas-kicker">Festival 2026</span>
<h1 class="canvas-title">Sound Canvas</h1>
<p class="canvas-lead mx-auto mx-lg-0">Three days of live music in Lisbon. Open the menu and the whole page makes room for it.</p>
<ul class="canvas-meta list-unstyled d-flex flex-wrap justify-content-center justify-content-lg-start gap-3 my-4">
<li>14–16 August</li><li>Parque Eduardo VII, Lisbon</li>
</ul>
<a href="#" class="btn btn-light rounded-pill px-4 canvas-cta">Get tickets</a>
</div>
<div class="col-lg-5 d-none d-lg-block" aria-hidden="true">
<div class="canvas-peek">
<span class="wdw-eyebrow">Navigation</span>
<ol class="list-unstyled m-0 mt-3">
<li><small>01</small>Home</li><li><small>02</small>Line-up</li><li><small>03</small>Tickets</li><li><small>04</small>Venue</li><li><small>05</small>Contact</li>
</ol>
</div>
</div>
</div>
</div>
<div class="offcanvas offcanvas-start canvas-panel" tabindex="-1" id="canvasNav" aria-labelledby="canvasNavLabel" data-bs-theme="dark">
<div class="offcanvas-header p-4 p-md-5 pb-0">
<span class="wdw-eyebrow" id="canvasNavLabel">Navigation</span>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close menu"></button>
</div>
<div class="offcanvas-body p-4 p-md-5 d-flex flex-column justify-content-center">
<nav aria-label="Main">
<ol class="canvas-links list-unstyled m-0">
<li style="--i:0"><a href="#"><small>01</small>Home</a></li>
<li style="--i:1"><a href="#"><small>02</small>Line-up</a></li>
<li style="--i:2"><a href="#"><small>03</small>Tickets</a></li>
<li style="--i:3"><a href="#"><small>04</small>Venue</a></li>
<li style="--i:4"><a href="#"><small>05</small>Contact</a></li>
</ol>
</nav>
</div>
</div>
</section>
/* Web Designer Wall library style — shared base for every Bootstrap 5 snippet.
Indigo accent, Plus Jakarta Sans, soft cards, pill buttons. Works in light and dark. */
@import url("https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap");
:root,
[data-bs-theme="light"] {
--wdw-font: "Plus Jakarta Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
--bs-body-font-family: var(--wdw-font);
--bs-primary: #4f46e5;
--bs-primary-rgb: 79, 70, 229;
--bs-primary-text-emphasis: #3730a3;
--bs-primary-bg-subtle: #eef2ff;
--bs-primary-border-subtle: #c7d2fe;
--bs-link-color: #4f46e5;
--bs-link-color-rgb: 79, 70, 229;
--bs-link-hover-color: #4338ca;
--bs-link-hover-color-rgb: 67, 56, 202;
--bs-focus-ring-color: rgba(79, 70, 229, 0.25);
--bs-border-radius: 0.75rem;
--bs-border-radius-lg: 1rem;
--bs-border-radius-xl: 1.25rem;
--wdw-radius-card: 1.25rem;
--wdw-shadow: 0 1px 2px rgba(16, 24, 40, 0.05), 0 16px 40px -16px rgba(16, 24, 40, 0.22);
--wdw-shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.06), 0 4px 12px -4px rgba(16, 24, 40, 0.12);
--wdw-stage: #f5f6fb;
}
[data-bs-theme="dark"] {
--bs-primary: #818cf8;
--bs-primary-rgb: 129, 140, 248;
--bs-primary-text-emphasis: #c7d2fe;
--bs-primary-bg-subtle: rgba(129, 140, 248, 0.14);
--bs-primary-border-subtle: rgba(129, 140, 248, 0.35);
--bs-link-color: #a5b4fc;
--bs-link-color-rgb: 165, 180, 252;
--bs-link-hover-color: #c7d2fe;
--bs-link-hover-color-rgb: 199, 210, 254;
--bs-focus-ring-color: rgba(129, 140, 248, 0.35);
--wdw-shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 16px 40px -16px rgba(0, 0, 0, 0.7);
--wdw-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 12px -4px rgba(0, 0, 0, 0.5);
--wdw-stage: #0f1117;
}
body { font-family: var(--wdw-font); -webkit-font-smoothing: antialiased; }
/* Bootstrap compiles its blue into these components; point them at the accent. */
.btn-primary {
--bs-btn-bg: var(--bs-primary); --bs-btn-border-color: var(--bs-primary);
--bs-btn-hover-bg: #4338ca; --bs-btn-hover-border-color: #4338ca;
--bs-btn-active-bg: #3730a3; --bs-btn-active-border-color: #3730a3;
--bs-btn-disabled-bg: var(--bs-primary); --bs-btn-disabled-border-color: var(--bs-primary);
--bs-btn-focus-shadow-rgb: var(--bs-primary-rgb);
}
[data-bs-theme="dark"] .btn-primary { --bs-btn-color: #0f1117; --bs-btn-hover-bg: #a5b4fc; --bs-btn-hover-border-color: #a5b4fc; --bs-btn-hover-color: #0f1117; --bs-btn-active-color: #0f1117; }
.btn-outline-primary {
--bs-btn-color: var(--bs-primary); --bs-btn-border-color: var(--bs-primary);
--bs-btn-hover-bg: var(--bs-primary); --bs-btn-hover-border-color: var(--bs-primary);
--bs-btn-active-bg: var(--bs-primary); --bs-btn-active-border-color: var(--bs-primary);
--bs-btn-focus-shadow-rgb: var(--bs-primary-rgb);
}
.btn { --bs-btn-font-weight: 600; min-height: 44px; display: inline-flex; align-items: center; justify-content: center; gap: .5rem; }
.btn-sm { min-height: 36px; }
.form-control, .form-select { min-height: 44px; border-radius: .75rem; }
.form-control:focus, .form-select:focus, .form-check-input:focus { border-color: rgba(var(--bs-primary-rgb), .6); box-shadow: 0 0 0 .25rem var(--bs-focus-ring-color); }
.form-check-input:checked { background-color: var(--bs-primary); border-color: var(--bs-primary); }
.nav-pills { --bs-nav-pills-link-active-bg: var(--bs-primary); }
.nav { --bs-nav-link-color: var(--bs-secondary-color); --bs-nav-link-hover-color: var(--bs-emphasis-color); }
.pagination { --bs-pagination-active-bg: var(--bs-primary); --bs-pagination-active-border-color: var(--bs-primary); --bs-pagination-color: var(--bs-body-color); --bs-pagination-focus-box-shadow: 0 0 0 .25rem var(--bs-focus-ring-color); }
.progress, .progress-stacked { --bs-progress-bar-bg: var(--bs-primary); }
.list-group { --bs-list-group-active-bg: var(--bs-primary); --bs-list-group-active-border-color: var(--bs-primary); }
.dropdown-menu { --bs-dropdown-link-active-bg: var(--bs-primary); border-radius: .875rem; box-shadow: var(--wdw-shadow-sm); }
.accordion { --bs-accordion-active-bg: var(--bs-primary-bg-subtle); --bs-accordion-active-color: var(--bs-primary-text-emphasis); --bs-accordion-btn-focus-box-shadow: 0 0 0 .25rem var(--bs-focus-ring-color); }
.badge { font-weight: 600; }
/* Library building blocks — use these instead of re-inventing them per snippet. */
.wdw-stage { min-height: 100vh; display: flex; align-items: center; background: var(--wdw-stage); padding-block: 3rem; }
.wdw-card { background: var(--bs-body-bg); border: 1px solid var(--bs-border-color-translucent); border-radius: var(--wdw-radius-card); box-shadow: var(--wdw-shadow); }
.wdw-card-sm { background: var(--bs-body-bg); border: 1px solid var(--bs-border-color-translucent); border-radius: 1rem; box-shadow: var(--wdw-shadow-sm); }
.wdw-aurora { position: relative; color: #fff; background: radial-gradient(60% 55% at 100% 0, #818cf8 0, transparent 70%), radial-gradient(65% 60% at 0 100%, #ec4899 0, transparent 65%), #1e1b4b; }
.wdw-eyebrow { display: inline-block; font-size: .75rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--bs-primary); }
.wdw-heading { font-weight: 800; letter-spacing: -.02em; color: var(--bs-emphasis-color); }
.wdw-muted { color: var(--bs-secondary-color); }
.wdw-icon { width: 2.75rem; height: 2.75rem; flex: none; display: inline-flex; align-items: center; justify-content: center; border-radius: .875rem; background: var(--bs-primary-bg-subtle); color: var(--bs-primary); }
/* Component */
.canvas-hero { min-height: 100vh; min-height: max(100vh, 560px); display: flex; flex-direction: column; overflow: hidden; }
.canvas-body { margin: auto; }
.canvas-meta li { font-weight: 600; font-size: .95rem; padding: .3rem .8rem; border: 1px solid rgba(255,255,255,.28); border-radius: 99px; }
.canvas-cta { --bs-btn-color: #1e1b4b; --bs-btn-hover-color: #1e1b4b; --bs-btn-active-color: #1e1b4b; }
.canvas-peek { padding: 2rem; border-radius: 1.25rem; background: rgba(15,12,45,.55); border: 1px solid rgba(255,255,255,.14); backdrop-filter: blur(6px); }
.canvas-peek .wdw-eyebrow { color: #c7d2fe; }
.canvas-peek li { display: flex; align-items: baseline; gap: 1rem; font-size: 2rem; font-weight: 800; letter-spacing: -.03em; line-height: 1.35; color: rgba(255,255,255,.85); }
.canvas-peek li small { font-size: .8rem; font-weight: 600; color: #c7d2fe; }
.canvas-kicker { display: inline-block; padding: .35rem .9rem; border-radius: 99px; background: rgba(255,255,255,.14); font-size: .8rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.canvas-title { font-size: clamp(2.6rem, 8vw, 5.5rem); font-weight: 800; letter-spacing: -.04em; margin: 1rem 0 .5rem; line-height: 1; }
.canvas-lead { max-width: 30rem; font-size: 1.1rem; color: rgba(255,255,255,.78); }
.canvas-menu-btn { --bs-btn-color: #1e1b4b; --bs-btn-bg: #fff; --bs-btn-border-color: #fff; --bs-btn-hover-bg: #eef2ff; --bs-btn-hover-color: #1e1b4b; --bs-btn-active-color: #1e1b4b; --bs-btn-active-bg: #e0e7ff; }
.canvas-panel { --bs-offcanvas-width: min(480px, 100vw); --bs-offcanvas-bg: var(--bs-body-bg); }
.canvas-panel::before { content: ""; position: absolute; inset: 0; pointer-events: none; background: radial-gradient(60% 40% at 100% 0, rgba(129,140,248,.28), transparent 70%), radial-gradient(60% 40% at 0 100%, rgba(236,72,153,.2), transparent 70%); }
.canvas-panel > * { position: relative; }
.canvas-links li { opacity: 0; transform: translateX(-2rem); }
.canvas-panel.show .canvas-links li { opacity: 1; transform: none; transition: opacity .5s ease, transform .5s cubic-bezier(.2,.8,.2,1); transition-delay: calc(.12s + var(--i) * .07s); }
.canvas-links a { display: flex; align-items: baseline; gap: 1rem; padding: .35rem 0; font-size: clamp(2rem, 7vw, 3.25rem); font-weight: 800; letter-spacing: -.03em; color: rgba(255,255,255,.55); text-decoration: none; transition: color .2s, padding-left .25s; }
.canvas-links a small { font-size: .85rem; font-weight: 600; color: var(--bs-primary); letter-spacing: .05em; }
.canvas-links a:hover, .canvas-links a:focus-visible { color: #fff; padding-left: .5rem; }
@media (prefers-reduced-motion: reduce) {
function initCanvasNav() {
const panel = document.getElementById('canvasNav');
if (!panel) return;
panel.querySelectorAll('a').forEach((link) => {
link.addEventListener('click', (e) => {
e.preventDefault();
bootstrap.Offcanvas.getOrCreateInstance(panel).hide();
});
});
}
initCanvasNav();
Built on Bootstrap 5.3.8 with plain JavaScript — no jQuery. Supports light and dark mode via data-bs-theme.