.off(events [, selector] [, handler]) removes handlers attached with .on() (since 1.7). Filter by event type, namespace, delegation selector, and/or function reference.
Remember
$("#btn").on("click", fn);
$("#btn").off("click", fn); // remove that handler
$("body").on("click", "#theone", flash);
$("body").off("click", "#theone", flash); // same selector required
$("form").off(".validator"); // all handlers in that namespace
$("p").off(); // remove everything on p
$("p").off("click", "**"); // all delegated clicks only
Match the same filters you used when calling .on().
Attach with .on() (direct or delegated).
Decide what to remove: all, one event type, a namespace, a selector, and/or a function.
Call .off() with those same filters on the same element(s).
For delegated handlers, pass the exact original selector string.
In shared code, prefer namespaces over bare .off("click").
Form
Role
.off()
Remove all handlers on the element(s)
.off(events [, selector] [, handler])
Filter by type / namespace / selector / function
.off(eventsObject [, selector])
Map of event → handler (or false)
.off(event)
Remove using a jQuery.Event object
Pseudocode
Pseudocode
handlers were attached with .on(...)
call .off(optional EVENTS, optional SELECTOR, optional HANDLER):
if no args:
remove all handlers on these elements
else:
keep only handlers that match EVERY filter you passed
delegated note:
SELECTOR must equal the original .on() selector
"**" means “any delegated selector” for that event
Reference
Cheat Sheet
Keep these removal patterns handy.
Topic
Detail
Returns
jQuery (chainable)
Since
1.7
Pairs with
.on()
Namespace
.off(".myPlugin") clears that namespace
"**"
All delegated handlers of that event type
Selector rule
Must match the original delegated selector exactly
Proxy tip
Prefer namespaces when unbinding proxied handlers
Try it
Live Preview
Bind a delegated click, fire it, then remove it with .off().
Run bind, click the target, then try an off action.
Status
Ready — Run “bind”, then click Target.
Code
jQuery Examples
Short, copy-ready snippets. Pair every .on() with a matching .off() when cleaning up.
Example 1 — Delegated Bind / Off
Attach a delegated click, then remove it with the same selector.
jQuery
function flash() {
$("#out").text("Clicked!");
}
$("#bind").on("click", function () {
$("body").on("click", "#theone", flash);
$("#theone").text("Can Click!");
});
$("#unbind").on("click", function () {
$("body").off("click", "#theone", flash);
$("#theone").text("Does nothing...");
});
Delegated li clicks stop
Direct #list click can still fire
How It Works
Two kinds. Direct handlers sit on the element; delegated ones filter children.
Star."**" means any delegated selector for that event.
Keep. Direct click on #list remains.
Use. Clear child delegation without resetting the parent’s own handlers.
Edge Cases & Pitfalls
Common mistakes when removing handlers.
selector
Delegated selector must match exactly
.on("click", "li.item", fn) is not removed by .off("click", "li", fn).
broad
.off("click") is wide
It removes both direct and delegated click handlers on that element — use namespaces when sharing.
proxy
Proxied handlers share ids
Passing a proxied function to .off() can remove more than you intend — prefer namespaces.
anonymous
Anonymous functions are hard to target
Keep a named reference, or remove by event type / namespace instead of by function.
Compatibility
Browser Support
.off() has been part of jQuery since 1.7 and remains the standard way to remove handlers. It works wherever your loaded jQuery version runs.
✓ Stable · jQuery 1.7+
.off()
Works in every browser that runs your loaded jQuery version. Prefer a current jQuery 3.x build for modern projects.
100%With jQuery 1.7+
Google ChromeAll versions · Desktop & Mobile
Full support
Mozilla FirefoxAll versions · Desktop & Mobile
Full support
Apple SafariAll versions · macOS & iOS
Full support
Microsoft EdgeAll versions · Chromium & Legacy
Full support
Internet ExplorerIE 6+ · Legacy environments
Full support
OperaAll modern versions
Full support
.off()Universal
Bottom line: Production-ready. Use namespaces for safe cleanup in plugins and shared pages.
Analysis
Performance Notes
Approach
Cost
Best for
Namespaced .off()
Tiny
Plugin / widget teardown
Leaving orphaned handlers
Memory leak risk
Always off when removing dynamic UI
Repeated bind without off
Higher
Handlers stack — off before re-on
Removing a handler is cheap. The expensive mistake is never removing them when elements or widgets are destroyed.
Remember
Key Takeaways
Role: remove handlers attached with .on().
Match: use the same event, selector, and function you used with .on().
Namespaces: safest cleanup for plugins — .off(".myPlugin").
"**": strip all delegated handlers of an event type, keep direct ones.
One line:.off() is the modern undo for .on() — filter carefully, prefer namespaces.
Frequently Asked Questions
.off() removes event handlers attached with .on(). Since jQuery 1.7 it is the standard unbind API for both direct and delegated handlers, replacing .unbind(), .undelegate(), and .die().
It removes all handlers from the matched elements — direct and delegated. Prefer narrower filters (event type, namespace, selector, or handler) unless you are tearing a widget down.
Pass the same selector you used with .on(). Example: $(body).on("click", "#theone", fn) then $(body).off("click", "#theone", fn). A mismatched selector will not remove it.
$(el).off("click", "**") removes all delegated click handlers from el without removing direct click handlers bound on el itself.
Namespaces such as click.myPlugin let you remove only your handlers with .off(".myPlugin") without touching other code. Best practice for plugins and large apps.
.unbind() only covered direct binds; .die() only removed .live() handlers (both legacy). .off() works with everything attached via .on(), including delegation.