Navigation and overlays
Drawer
A side panel toggled by a hidden checkbox and its labels, with a dimmed overlay that closes it. Works without JavaScript and without a dialog.
Example
<div class="drawer"><input id="nav-drawer" type="checkbox" class="drawer-toggle"><div class="drawer-content"><label for="nav-drawer" class="inline-flex items-center justify-center gap-2 rounded-lg border border-border bg-surface px-4 py-2 text-sm font-medium hover:bg-muted cursor-pointer">Open menu</label></div><div class="drawer-side"><label for="nav-drawer" class="drawer-overlay" aria-label="Close menu"></label><nav class="drawer-panel" aria-label="Main"><p class="px-3 text-base font-semibold">Acme Studio</p><ul class="menu"><li><a href="#" aria-current="page"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 10.5 12 3l9 7.5V20a1 1 0 0 1-1 1h-5v-6H9v6H4a1 1 0 0 1-1-1z"/></svg>Dashboard</a></li><li><a href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg>Projects</a></li><li><a href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="9" cy="8" r="4"/><path d="M2 21a7 7 0 0 1 14 0M16 4a4 4 0 0 1 0 8M22 21a7 7 0 0 0-4-6.3"/></svg>Team</a></li><li><a href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="3"/><path d="M12 2v3M12 19v3M4.9 4.9 7 7M17 17l2.1 2.1M2 12h3M19 12h3M4.9 19.1 7 17M17 7l2.1-2.1"/></svg>Settings</a></li></ul></nav></div></div>Classes
6 classes. Click a name to copy it. Utilities on the same element always win over component defaults, so any of them can be adjusted with plain utility classes.
| Class | Type | What it does |
|---|---|---|
| Base | Base class of the drawer. On a <div> in the example. Sets overflow, grid display, grid tracks and width, and 8 custom properties.CSS |
|
| Part | Part of the drawer. On an <input> in the example. Sets fixed position, width, height, opacity, native control styling and transition.CSS |
|
| Part | Part of the drawer. On a <div> in the example. Sets grid tracks and width.CSS |
|
| Part | Part of the drawer. On a <div> in the example. Sets fixed position, offsets, stacking order, grid display, grid tracks and overflow.CSS |
|
| Part | Part of the drawer. On a <label> in the example. Sets block display, background, opacity, pointer cursor and transition.CSS |
|
| Part | Part of the drawer. On a <nav> in the example. Sets flex display, alignment, gap, width, height and padding.CSS |
Usage
Components ship inside the same stylesheet as the utilities. There is nothing else to install and no script to load: link Monsoon and write the markup.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/monsooncss">
<!-- Drawer: start from the base class, then add modifiers -->
<div class="drawer"><input id="nav-drawer" type="checkbox" class="drawer-toggle"><div class="drawer-content"><label for="nav-drawer" class="inline-flex items-center justify-center gap-2 rounded-lg border border-border bg-surface px-4 py-2 text-sm font-medium hover:bg-muted cursor-pointer">Open menu</label></div><div class="drawer-side"><label for="nav-drawer" class="drawer-overlay" aria-label="Close menu"></label><nav class="drawer-panel" aria-label="Main"><p class="px-3 text-base font-semibold">Acme Studio</p><ul class="menu"><li><a href="#" aria-current="page"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 10.5 12 3l9 7.5V20a1 1 0 0 1-1 1h-5v-6H9v6H4a1 1 0 0 1-1-1z"/></svg>Dashboard</a></li><li><a href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg>Projects</a></li><li><a href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="9" cy="8" r="4"/><path d="M2 21a7 7 0 0 1 14 0M16 4a4 4 0 0 1 0 8M22 21a7 7 0 0 0-4-6.3"/></svg>Team</a></li><li><a href="#"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="3"/><path d="M12 2v3M12 19v3M4.9 4.9 7 7M17 17l2.1 2.1M2 12h3M19 12h3M4.9 19.1 7 17M17 7l2.1-2.1"/></svg>Settings</a></li></ul></nav></div></div>Theme it with --seed on any ancestor, for example style="--seed: #0d9488", and force a scheme with class="dark" or class="light" on a wrapper.
Accessibility
- Give every control a visible
labellinked withfor, or anaria-labelwhen the purpose is obvious from context. Link help and error text witharia-describedby; invalid styles use:user-invalid, so they appear only after the user interacts. - Checkboxes and radios stay real inputs, so they keep native keyboard behavior (Space toggles, arrow keys move within a radio group) and form submission.
- Wrap navigation in
navwith anaria-labelwhen there is more than one on the page, and mark the current link witharia-current="page". - Every interactive part shows a visible focus ring with
:focus-visible, and tone colors pair with-foregroundtokens that keep text at 4.5:1 or better in light and dark mode.