@bgunnarsson/click-outside
v1.0.1
Published
0 dependency outside click utility.
Maintainers
Readme
click-outside
A tiny, framework-agnostic utility that closes all elements with an .open class when clicking or tapping outside them — just like dropdowns, popovers, and menus do.
✅ Shadow DOM–safe
✅ ESC key support
✅ .co-trigger / ignore selectors
✅ Custom events (will-close-outside / did-close-outside)
✅ Fully typed via JSDoc
📦 Installation
pnpm i @bgunnarsson/click-outside
# or
npm install @bgunnarsson/click-outside
# or
yarn add @bgunnarsson/click-outside⚙️ Usage
// clickOutside.mjs
import { clickOutside } from 'click-outside-global';
// initialize once at app startup
const dispose = clickOutside({
openSelector: '.open', // elements that should close
triggerSelector: '.co-trigger', // ignore trigger clicks
escape: true, // also close on Escape
});
// later, if you want to stop listening:
dispose();Example HTML
<button class="co-trigger">Toggle menu</button>
<div class="dropdown open">
<p>Dropdown content</p>
</div>When you click anywhere outside .dropdown and not inside .co-trigger,
the .open class will be removed from all elements with .open.
🧠 Custom Events
Each open element emits two events when closing:
| Event | Cancelable | Description |
|--------|-------------|-------------|
| will-close-outside | ✅ Yes | Fired before removal. Call event.preventDefault() to cancel. |
| did-close-outside | ❌ No | Fired after .open was removed. |
Example
document.addEventListener('will-close-outside', (e) => {
const el = e.target;
console.log('About to close:', el);
// Cancel close for sticky elements
if (el.matches('[data-sticky]')) e.preventDefault();
});
document.addEventListener('did-close-outside', (e) => {
const el = e.target;
console.log('Closed:', el);
});🧩 Options
| Option | Type | Default | Description |
|--------|------|----------|-------------|
| openSelector | string | '.open' | Selector for open elements. |
| triggerSelector | string | – | Selector for elements that should not close when clicked (e.g. .co-trigger). |
| ignore | (Element \| string \| (node: Node) => boolean)[] | [] | Additional elements, selectors, or predicates to ignore. |
| event | 'pointerdown' \| 'mousedown' \| 'click' | 'pointerdown' | DOM event to listen for. |
| escape | boolean | true | Close on Escape key. |
| capture | boolean | true | Use capture phase (recommended). |
| root | Document \| DocumentFragment | document | Scope for querying open elements. |
🧪 License
MIT © 2025 B. Gunnarsson
