02UI

Drawer

A drawer slides in from the edge of the screen and keeps the page behind it visible, dimmed but still there. That's the whole difference from a modal: a drawer lets you glance back at what you were looking at.

OverlaysBuild difficulty: Medium<div role="dialog">

Also called Side panel, Slide-over, Bottom sheet, Off-canvas panel.

A drawer is what a modal turns into once you decide the page behind it still matters. Filtering a table, inspecting a row, editing something you want to compare against the list it came from: all of it is easier with the original context still on screen.

Anatomy of a drawer

Anatomy of a drawer: the backdrop dimming the page, the panel sliding from the edge, the drag handle on a bottom sheet, the title, the body content, and the footer actions.
  1. 1Backdrop. Dims the page behind the panel without hiding it, the detail that separates a drawer from a modal.
  2. 2Panel. Slides in from a screen edge and holds everything else. Where focus is trapped while the drawer is open.
  3. 3Handle. A drag affordance on a bottom sheet, used to pull it further open or flick it closed. A side panel has no equivalent.
  4. 4Title. Names the task, tied to the panel with aria-labelledby.
  5. 5Body. The content itself: a filter form, a set of options, a detail view.
  6. 6Actions. The footer buttons, when the drawer needs a way to commit or cancel rather than just close.

The handle only shows up on a bottom sheet. A side panel doesn't need one, because the edge it slides from is already the affordance.

Here it is working. Open it, then close it by clicking outside, pressing Escape, or using the close control.

Open it, then close it by clicking outside, pressing Escape, or the close control.

When to use a drawer

Use a drawer when

  • Someone benefits from comparing the drawer's content against the page behind it, like a filter panel next to the list it filters
  • The content is naturally a list, a form, or a set of options rather than a single decision to force
  • You're on a narrow viewport and the content needs more room than a popover gives, without leaving the current screen (a bottom sheet)
  • Dismissing it costs nothing. Swiping it away or tapping outside should never lose anything that mattered

Reach for something else when

  • The action is destructive, or the task genuinely needs to block the page until it's dealt with. Use a modal instead.
  • The content is a short, contextual detail tied to one specific control, like a date range or a colour swatch. Use a popover instead.
  • The content deserves its own URL, its own back button, or a bookmark someone might return to. That's a page, not an overlay.
  • You're opening a drawer from inside another drawer or a modal. Close the first layer, or combine the two tasks into one.

Variants

Right for a details panel, left for navigation, bottom for a mobile sheet.

Right. The default for a details panel or a form tied to a row or a card. Reading direction in most languages moves left to right, so a panel from the right reads as an addition to what you were already looking at.

Left. Reserved for navigation, the same place a fixed sidebar would live if there were room for one permanently.

Bottom. The mobile pattern. Opens with a downward-flick gesture to close, sits within thumb's reach, and never has to travel the full width of the screen the way a side panel would.

States

Closed
Open
Filter results
Owned by me
Apply filters
Dragging
Sort by

Released between the handle and the fingertip.

Closing
Filter results

Sliding back toward the edge it came from.

StateWhat changesWatch out for
ClosedNothing rendered, trigger sits at restTrigger looks interactive on its own, with no hint required to know it opens something
OpenPanel slides in, backdrop dims the pageFocus lands inside immediately, not left on the trigger behind the backdrop
DraggingBottom sheet follows the pointer or fingerSnap back if released before crossing the dismiss threshold, close if released past it
ClosingReverse of the open transitionFocus returns to the trigger once the panel finishes leaving

The dragging state only applies to a touch-driven bottom sheet. A side panel on desktop has no equivalent, it opens and closes on a fixed transition with nothing to drag.

How a drawer behaves

Slides from a screen edge, rather than scaling up from the centre the way a modal does. The direction of motion is what tells someone where it came from and where closing it will send it back to.

The page behind it stays visible, dimmed by a backdrop but not replaced by one. Someone can still see the list a filter drawer is about to change.

Focus moves into the drawer on open, the same rule a modal follows, landing on the first focusable element or the heading.

Focus is trapped while it's open, when the drawer has a backdrop and blocks the page behind it, which is the common case. Tab cycles inside the panel only.

Escape and a backdrop click both close it, unless the content has unsaved changes worth confirming first, the same exception a modal makes.

Dragging a bottom sheet follows the gesture in real time. Releasing past roughly a third of the panel's height closes it. Releasing before that snaps it back open. A drawer that ignores the gesture entirely and only responds to a dedicated close button feels stuck on a touchscreen.

Only one drawer opens at a time. Opening a second closes whatever was already open, same as a modal.

Drawer accessibility

Keyboard

KeyWhat happens
Tab / Shift+TabCycles focus through the drawer's own controls only, wrapping at both ends
EscapeCloses the drawer and returns focus to the trigger
Enter / SpaceActivates the focused control

The rest

  • Role and state. role="dialog" with aria-modal="true" when it blocks the page, the same pattern a modal uses. A non-modal drawer that leaves the page interactive should drop aria-modal entirely rather than set it to false, since some assistive tech ignores the false value.
  • Name it. aria-labelledby pointing at the drawer's own heading.
  • Background inert while modal. The same inert treatment a modal needs on everything outside the panel.
  • Contrast. The panel needs to read as a distinct surface against the dimmed page behind it, and any text inside needs 4.5:1 against the panel background (WCAG 1.4.3).
  • Target size. The drag handle and close control both need 24 by 24 CSS pixels at minimum (WCAG 2.5.8), more on a touch-first bottom sheet, where 44 by 44 points is the safer target.

What a drawer should say

Title names what's inside, not the mechanism. "Filter results" beats "Filters panel", because the second one describes the component instead of the task.

Keep the primary action within reach without scrolling on a bottom sheet. Someone dragging a sheet up on a small phone shouldn't have to hunt for the button that finishes the job.

Empty states inside a drawer still need a next step. A filter drawer with no matches should say so and suggest clearing a filter, not just render a blank list underneath.

Common drawer mistakes

The most common failure looks identical to a broken modal, because most drawer bugs are modal bugs wearing a different animation.

Do
Filter results

A close button sits in the corner, same as a modal.

A visible close control works for anyone who doesn't know or can't perform the backdrop click or swipe.

Don't
Filter results

Closes only on a backdrop click or a swipe. Nothing on the panel itself does it.

Anyone who doesn't discover the backdrop click or the swipe gesture is stuck with the panel open.

1. No visible way to close it. Relying on a backdrop click or a swipe gesture alone leaves out anyone who doesn't discover either.

2. Backdrop click silently discards a form. The same rule a modal follows: confirm first, or hold off on backdrop dismissal, when there's unsaved input.

3. No focus trap on a modal drawer. Tab walks straight into the page behind it while the drawer is still open and still blocking clicks, which is a worse mismatch than a modal makes because the page is visibly right there, inviting the attempt.

4. A side drawer used for a destructive confirmation. Keeping the page visible undersells how serious the action is. Reach for a modal instead.

5. A bottom sheet that ignores the drag gesture. Feels broken on a touchscreen the first time someone tries the obvious swipe and nothing happens.

6. Content taller than the panel with no internal scroll. A drawer that just runs off the bottom of the screen, with no way to reach what's below, loses everything past the fold.

How to build a drawer

<div class="drawer-backdrop"></div>
<div role="dialog" aria-modal="true" aria-labelledby="drawer-title" class="drawer drawer--right">
  <h2 id="drawer-title">Filter results</h2>
  <button aria-label="Close">×</button>
  <!-- drawer content -->
</div>
const drawer = document.querySelector(".drawer");
const backdrop = document.querySelector(".drawer-backdrop");

function open() {
  drawer.classList.add("is-open");
  backdrop.classList.add("is-open");
  drawer.querySelector("button, [href], input, select, textarea").focus();
}

function close() {
  drawer.classList.remove("is-open");
  backdrop.classList.remove("is-open");
  trigger.focus();
}

backdrop.addEventListener("click", close);
drawer.addEventListener("keydown", (e) => e.key === "Escape" && close());

That's the shape of it. What it leaves out, focus trapping inside the panel, the drag-to-dismiss gesture on a bottom sheet, and the position-aware slide transition, is most of the actual difficulty. Vaul, the library behind this site's own drawer, and Radix's dialog primitive underneath it, handle all three. Reach for one of those before building this by hand.

Edge cases

A drawer taller than the viewport. Scroll inside the panel body, with a fixed header and footer, the same pattern a modal uses for long content.

Resizing while open, say rotating a phone from portrait to landscape. Recalculate the panel's height rather than leaving a bottom sheet sized for the orientation it opened in.

A drawer opened from inside a modal. Close the modal first. Two overlays with two separate focus traps competing for the same Tab key is not a supported combination in any major implementation.

Reduced motion. Respect prefers-reduced-motion and drop the slide to a plain fade, or remove the transition entirely.

Nested scrollable regions. A bottom sheet containing its own scrollable list needs the drag gesture and the list's scroll to not fight each other, usually resolved by only starting the drag when the list is already scrolled to its top.

Drawers in real products

Linear opens a side panel from the right when you click into an issue from a list, keeping the list scrollable and visible behind it so switching between issues doesn't cost a full navigation.

Google Maps uses a bottom sheet on mobile for place details, letting someone drag it up for the full description or down to see more of the map underneath.

Notion slides a comments panel in from the right on a page, next to the content it's commenting on rather than over it, which is the clearest case for why a drawer exists instead of a modal.

Common questions

What's the real difference between a drawer and a modal?
A modal blocks the page and hides it behind an opaque-feeling overlay, demanding a decision. A drawer dims the page but keeps it visible and often keeps it scrollable, so someone can check something on the page without closing the drawer first. If the task needs a hard stop, it's a modal. If it benefits from staying in view, it's a drawer.
Should a drawer have a backdrop?
Usually, yes, dimmed enough to show the drawer has focus without hiding the page completely. A drawer with no backdrop at all reads as part of the page's permanent layout rather than a temporary overlay, which makes it easy to forget it's still open.
Bottom sheet or side drawer, which one for mobile?
Bottom sheet, in almost every case. It opens with a natural downward gesture to dismiss, sits within thumb's reach, and doesn't need to travel the full width of a phone screen. Reserve a side drawer on mobile for navigation that already has a fixed, learned position, like a main menu.
Does a drawer need to trap focus like a modal?
If it has a backdrop and blocks interaction with the page (the common case), yes, the same focus trap a modal needs. A non-modal drawer that lets someone keep clicking the page behind it, less common but valid for something like a persistent inspector panel, does not need to trap focus, but then nothing behind it should assume the drawer is out of the way.
Can a drawer open from any edge?
Left and right are the common ones for a side panel, bottom for a mobile sheet. Top is rare and mostly reserved for a search overlay or a notification tray. Whichever edge, keep it consistent for the same kind of content across your product.

Last reviewed 29 JUL 2026