Off-canvas

오프캔버스

A panel that hides off-screen and slides in from an edge on demand — the mechanism behind the mobile hamburger menu.

Also known as: Off-canvas menuSlide-out drawer
···
html
<div class="phone">
  <header>☰ &nbsp; App</header>
  <div class="content"><i class="ln"></i><i class="ln"></i><i class="ln"></i></div>
  <div class="scrim show" id="scrim"></div>
  <div class="drawer show" id="drawer">
    <b>Menu</b>
    <i class="item"></i><i class="item"></i><i class="item"></i><i class="item"></i>
  </div>
</div>
css
.phone{position:relative;width:min(64%,230px);height:min(92%,300px);border:1px solid var(--line);border-radius:16px;
  overflow:hidden;box-shadow:0 8px 24px rgba(0,0,0,.12);background:var(--bg)}
header{background:var(--surface);border-bottom:1px solid var(--line);padding:12px;font-size:12px;font-weight:700}
.content{padding:16px;display:flex;flex-direction:column;gap:12px}
.content .ln{display:block;height:12px;border-radius:4px;background:var(--surface);border:1px solid var(--line)}
.scrim{position:absolute;inset:0;background:rgba(0,0,0,.4);opacity:0;pointer-events:none;transition:opacity .4s}
.scrim.show{opacity:1}
.drawer{position:absolute;top:0;bottom:0;left:0;width:68%;background:var(--surface);border-right:1px solid var(--line);
  transform:translateX(-100%);transition:transform .4s cubic-bezier(.2,.8,.2,1);padding:16px;display:flex;flex-direction:column;gap:10px}
.drawer.show{transform:translateX(0)}
.drawer b{font-size:12px}
.item{display:block;height:10px;border-radius:3px;background:var(--line);width:70%}
js
const drawer = document.getElementById('drawer');
const scrim = document.getElementById('scrim');
setInterval(() => {
  drawer.classList.toggle('show');
  scrim.classList.toggle('show');
}, 2200);

You position the element off the visible canvas ahead of time and slide it in with transform: translateX(). Not display: none — transform is GPU-accelerated, so it's smoother and animatable.

Pair it with a darkened overlay (scrim) so users understand focus has shifted to the panel, and clicking the overlay closes it. Lock background scrolling while the panel is open (overflow: hidden on body), or the page and the panel scroll together in a confusing way.

Beyond nav menus, the same pattern covers carts, filter panels and notification trays — anything that needs most of the screen briefly without being a full separate page.

When to use

Good for tucking away secondary navigation or extras on narrow mobile screens. For something used constantly, an always-visible UI like a bottom tab bar beats hiding it off-canvas.