jQuery .off() Method

Beginner
⏱️ 11 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Unbind handlers

What You’ll Learn

The .off() method removes event handlers attached with .on(). This tutorial covers all official signatures, five worked examples from the jQuery API, delegated unbinding with the ** selector, namespace cleanup, comparison with legacy .die(), and best practices for plugin authors.

01

Syntax

.off(type, sel, fn)

02

Pair

Undoes .on()

03

Delegate

Match selector

04

Namespaces

.off(".ns")

05

**

Delegated only

06

Since 1.7

Modern API

Introduction

Binding events is only half the story. When widgets are destroyed, routes change in a single-page app, or AJAX replaces DOM sections, you must remove handlers to prevent memory leaks and duplicate callbacks. jQuery unified unbinding in version 1.7 with .off(), the counterpart to .on().

Before 1.7, developers juggled three methods: .unbind() for direct handlers, .undelegate() for delegated ones, and .die() for legacy .live() handlers. Today, .off() handles all cases with one flexible API — filter by event type, delegation selector, handler function, or namespace.

Understanding .off()

.off() does not remove elements from the DOM — it detaches JavaScript functions from jQuery’s internal event registry. When you call .off("click", "#btn", fn), jQuery finds the handler that matches all provided filters and removes it. Omit filters to remove broader sets of handlers.

For delegated events, the selector argument must exactly match what you passed to .on(). If you bound on body with .on("click", "#theone", flash), unbind with .off("click", "#theone", flash) on the same element.

💡
Beginner Tip

Think of .on() and .off() as opposites with identical argument patterns (except .on() also accepts eventData). Bind with .on("click.myApp", "li", fn); tear down with .off("click.myApp", "li", fn) or simply .off(".myApp").

📝 Syntax

Four signatures from the official jQuery API (all since 1.7):

1. Filtered removal — .off( events [, selector ] [, handler ] )

jQuery
.off( events [, selector ] [, handler ] )
  • events — event type(s), optional namespace (e.g. "click", "click.myPlugin", ".myPlugin").
  • selector — delegation selector that must match .on(); use "**" for all delegated handlers of a type.
  • handler — specific function reference previously passed to .on().

2. Events map — .off( events [, selector ] )

jQuery
$( "#form" ).off({
  "click.validator": validate,
  "keypress.validator": validate
} );

3. From event object — .off( event )

jQuery
$( "#btn" ).on( "click", function( event ) {
  // Remove this handler after first click
  $( this ).off( event );
} );

4. Remove all — .off()

jQuery
$( "p" ).off();  // every handler on matched p elements

Legacy migration template

jQuery
// .unbind()  →  .off()
$( "#btn" ).unbind( "click", fn );
$( "#btn" ).off( "click", fn );

// .undelegate()  →  .off()
$( "#list" ).undelegate( "li", "click", fn );
$( "#list" ).off( "click", "li", fn );

// .die()  →  .off() on document
$( "p" ).die( "click", fn );
$( document ).off( "click", "p", fn );

Return value

  • Returns the original jQuery object for chaining.
  • When multiple filters are provided, all must match for a handler to be removed.

⚡ Quick Reference

GoalCode
Remove all handlers$("p").off()
Remove all click handlers$("#btn").off("click")
Remove delegated click only$("#list").off("click", "**")
Remove one delegated handler$("body").off("click", "p", fn)
Remove namespace handlers$("form").off(".validator")
Added injQuery 1.7

📋 .off() vs .die() vs .undelegate() vs .unbind()

Four unbinding methods from different jQuery eras. Only .off() should be used in modern projects.

.off()
.on() pair

Modern unified unbind since 1.7 — direct and delegated

.unbind()
.bind() pair

Direct handlers only — deprecated 3.0

.undelegate()
.delegate() pair

Delegated on root — deprecated 3.0

.die()
.live() pair

Document-level live handlers — removed 1.9

Examples Gallery

All five examples follow the official jQuery API documentation for .off(). Use the Try-it links to bind and unbind handlers interactively.

📚 Official API Examples

Five patterns from api.jquery.com/off/.

Example 1 — Add and Remove a Delegated Click Handler

The official interactive demo: bind flash on #theone, then remove it with matching .off().

jQuery
function flash() {
  $( "div" ).show().fadeOut( "slow" );
}

$( "#bind" ).on( "click", function() {
  $( "body" )
    .on( "click", "#theone", flash )
    .find( "#theone" )
    .text( "Can Click!" );
} );

$( "#unbind" ).on( "click", function() {
  $( "body" )
    .off( "click", "#theone", flash )
    .find( "#theone" )
    .text( "Does nothing..." );
} );
Try It Yourself

How It Works

Delegation binds on body for clicks matching #theone. .off("click", "#theone", flash) requires the same element, event type, selector, and function reference used during binding.

Example 2 — Remove All Event Handlers

Calling .off() with no arguments clears every handler on matched elements.

jQuery
$( "p" ).off();
Try It Yourself

How It Works

No filters means jQuery removes all direct and delegated handlers from each matched p. Use sparingly in shared code — prefer namespaces or specific handler references.

Example 3 — Remove All Delegated Click Handlers with "**"

Strip delegated clicks without removing direct click handlers on the same element.

jQuery
$( "p" ).off( "click", "**" );
Try It Yourself

How It Works

The special selector "**" targets only handlers attached via delegation (with a child selector in .on()). Direct handlers bound with .on("click", fn) on the same element survive.

Example 4 — Remove One Handler by Function Reference

Official pattern: pass the same foo function given to .on().

jQuery
var foo = function() {
  // Code to handle some kind of event
};

$( "body" ).on( "click", "p", foo );
$( "body" ).off( "click", "p", foo );
Try It Yourself

How It Works

Store handler functions in named variables so you can pass the identical reference to both .on() and .off(). Anonymous inline functions cannot be removed this way unless you keep a reference.

Example 5 — Remove Handlers by Namespace

Plugin-friendly cleanup: attach under .validator, remove all at once.

jQuery
var validate = function() {
  // Code to validate form entries
};

$( "form" ).on( "click.validator", "button", validate );
$( "form" ).on( "keypress.validator", "input[type='text']", validate );

$( "form" ).off( ".validator" );
Try It Yourself

How It Works

Namespaces segment your handlers from other code’s handlers. Passing only ".validator" to .off() removes every handler attached with that namespace, regardless of event type.

🚀 Common Use Cases

  • Widget teardown$("#widget").off(".myWidget") when removing a UI component.
  • Toggle binding — official bind/unbind button pattern from Example 1.
  • SPA route changes$(document).off("click.myRoute", ".nav-link") before attaching new route handlers.
  • One-time handlers$(this).off(event) inside the handler after first run.
  • Plugin isolation — namespace all bindings so .off() never removes foreign handlers.
  • Migrating from .die() — replace $("p").die("click") with $(document).off("click", "p").

🧠 How .off() Finds Handlers to Remove

1

Collect filters

jQuery reads your arguments: event type, namespace, delegation selector, handler function, or event object.

Parse
2

Scan registry

It searches the internal handler list on each matched element for entries that satisfy all filters.

Match
3

Detach matches

Matching handlers are removed from jQuery’s event data and will no longer fire.

Remove
4

Non-matches stay

Handlers that fail any filter remain active — enabling precise, scoped cleanup.

📝 Notes

  • .off() was added in jQuery 1.7 as the unified replacement for .unbind(), .undelegate(), and (conceptually) .die().
  • Calling .off("click") removes both direct and delegated click handlers unless you use "**" for delegated-only removal.
  • Proxied handlers ($.proxy()) share one internal id — prefer namespaces when unbinding proxied functions.
  • Minimum requirement: provide either an event name or a namespace (e.g. ".myPlugin" alone is valid).
  • .off(event) removes the specific handler that is currently executing — useful for one-shot handlers.
  • Legacy: $(document).off("click") removes all document-level delegated clicks, including those that replaced .live().

Browser Support

.off() is a jQuery method available since jQuery 1.7 in all jQuery 1.x, 2.x, and 3.x releases. It works in every browser your jQuery version supports. Native equivalent: element.removeEventListener(type, fn) — but without jQuery's delegation, namespace, or multi-handler management.

jQuery 1.7+

jQuery .off()

Supported in jQuery 1.7+ across all modern browsers and IE with supported jQuery builds. The current recommended way to remove handlers bound with .on(). Safe for all new jQuery projects.

100% Modern jQuery API
Google Chrome All versions · Desktop & Mobile
Full support
Mozilla Firefox All versions · Desktop & Mobile
Full support
Apple Safari All versions · macOS & iOS
Full support
Microsoft Edge All versions · Chromium & Legacy
Full support
Internet Explorer IE 6+ · Legacy environments
Full support
Opera All modern versions
Full support
.off() Universal

Bottom line: Use .off() in every jQuery 1.7+ project. Pair it with namespaced .on() bindings for safe plugin teardown. Never use removed .die() or deprecated .unbind() in new code.

Conclusion

jQuery .off() completes the modern event API started by .on() in version 1.7. Whether you need to remove one delegated handler, clear an entire namespace, or tear down a widget completely, .off() provides the filters to do it precisely.

Bind with namespaces, store handler references when you need surgical removal, and use "**" when you only want to drop delegated handlers. Practice the official bind/unbind demo until .on() / .off() feel like two halves of one pattern.

💡 Best Practices

✅ Do

  • Namespace plugin handlers: .on("click.myPlugin", fn)
  • Store handler refs when you need targeted .off(type, sel, fn)
  • Match delegation selectors exactly between .on() and .off()
  • Use .off(".myPlugin") for clean widget destruction
  • Prefer .off("click", "**") over bare .off("click") when keeping direct handlers

❌ Don’t

  • Call $("body").off() casually — it removes everything on body
  • Pass a different selector than you used in .on()
  • Rely on .off(fn) for proxied handlers bound to different contexts
  • Forget to unbind before re-binding the same event (causes duplicate handlers)
  • Use deprecated .unbind() or .die() in new jQuery 3 code

Key Takeaways

Knowledge Unlocked

Six things to remember about .off()

The modern way to unbind jQuery events.

6
Core concepts
🗑 02

.off()

Remove all.

Broad
** 03

Delegated

Only delegated.

Filter
.ns 04

Namespace

.off(".ns")

Plugins
fn 05

By ref

Same function.

Surgical
1.7 06

Modern

Use today.

Status

❓ Frequently Asked Questions

.off() removes event handlers that were attached with .on(). It is the modern unbinding API introduced in jQuery 1.7, replacing .unbind(), .undelegate(), and .die(). You can remove all handlers, filter by event type, delegation selector, handler function, or namespace.
.off() removes handlers bound with .on() — both direct and delegated. .die() only removed handlers attached with the removed .live() method. Migration: $('p').live('click', fn) became $(document).on('click', 'p', fn), and $('p').die('click') became $(document).off('click', 'p').
The special selector '**' removes all delegated click handlers from the element without removing direct click handlers bound on the element itself. Use it when you delegated with .on('click', 'li', fn) on a parent and want to clear only those delegated bindings.
Namespaces like .on('click.myPlugin', fn) let you remove only your plugin's handlers with .off('.myPlugin') without affecting other code. This is essential in large apps and plugins to avoid accidentally removing unrelated handlers.
Yes. If you bound with .on('click', '#theone', fn), you must pass the same '#theone' selector to .off(). A mismatched selector will not remove the handler.
All event handlers attached to the matched elements are removed — both direct and delegated. Use this carefully during widget teardown, or prefer scoped removal with event types, namespaces, or handler references.
Did you know?

When jQuery 1.7 shipped .on() and .off(), it retired three separate unbinding methods at once. A single call like $(document).off("click") can remove handlers that would have previously required knowing whether they were bound via .bind(), .delegate(), or .live() — which is why migrating legacy code to .on() / .off() simplifies maintenance dramatically.

Next: .unbind() Method

Learn the legacy .bind() counterpart and how to migrate to .off().

.unbind() tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful