jQuery Events: Stop (Mis)Using Return False
Probably one of the first topics covered when you get started learning about jQuery events is the concept of canceling the browser’s default behavior. For instance, a beginner click tutorial may include this:
$("a.toggle").click(function () {
$("#mydiv").toggle();
return false; // Prevent browser from visiting `#`
});
This function toggles the hiding and displaying of #mydiv, then cancels the browser’s default behavior of visiting the href of the anchor tag.
It is in these very first examples that bad habits are formed as users continue to use return false; whenever they want to cancel the default browser action. I am going to cover two very important topics in this article relating to the canceling of browser events:
- Use the right method for the job:
return falsevs.preventDefault,stopPropagation, andstopImmediatePropagation - Top, bottom or somewhere in the middle: where in the event callback should you cancel default behavior?
Note: in this article when I refer to event bubbling, I am talking about how most events will fire on the original DOM element, and then on each parent element in the DOM tree. Events do not bubble to siblings or children (When events “bubble” downward, it is called event capturing). Learn more about bubbling and capturing.
Use the Right Method for the Job
The main reason return false is so widely misused is because it appears to be doing what we want. Link callbacks no longer redirect the browser, form submit callbacks no longer submit the form, etc. So why is it so bad?
What return false is really doing
First off, return false is actually doing three very separate things when you call it:
- event.preventDefault();
- event.stopPropagation();
- Stops callback execution and returns immediately when called.
“Wait a minute,” you cry! I only needed to stop the default behavior! I don’t need these other two items… I think.
The only one of those three actions needed to cancel the default behavior is preventDefault(). Unless you mean to actually stop event propagation (bubbling), using return false will greatly increase the brittleness of your code. Lets see how this misuse plays out in a real world scenario:
Here is our HTML for the example:
<div class="post">
<h2><a href="/path/to/page">My Page</a></h2>
<div class="content">
Teaser text...
</div>
</div>
<div class="post">
<h2><a href="/path/to/other_page">My Other Page</a></h2>
<div class="content">
Teaser text...
</div>
</div>
Now lets say we want the actual article to load into the corresponding div.content when a user clicks on either title link:
jQuery(document).ready(function ($) {
$("div.post h2 a").click(function () {
var a = $(this),
href = a.attr('href'), // Let jQuery normalize `href`,
content = a.parent().next();
content.load(href + " #content");
return false; // "cancel" the default behavior of following the link
});
});
All is well (currently) and our dynamic page is well under way. Down the road we decide another piece of functionality we want is to add the class "active" to any div.post that has been clicked (or when a child element has been clicked) most recently. So, we decide to add a click handler to them as well:
// Inside Document Ready:
var posts = $("div.post");
posts.click(function () {
// Remove active from all div.post
posts.removeClass("active");
// Add it back to this one
$(this).addClass("active");
});
Will this work when we click a title link? NO! The reason it won’t work is because we used return false in the link click event instead of using what we really meant! Because return false really means event.preventDefault(); event.stopPropagation(); the click event never bubbled up to the parent div.post and our new event has not been called.
This becomes even more of an issue when mixing normal events with live or delegate events:
$("a").click(function () {
// do something
return false;
});
$("a").live("click", function () {
// THIS WON'T FIRE
});
So what DO you really want?
preventDefault()
In most situations where you would use return false what you really want is e.preventDefault(). Using preventDefault requires you allow for the event parameter to be accessed in your callback (In this example, I use e):
$("a").click(function (e) {
// e == our event data
e.preventDefault();
});
This does everything we want without prohibiting parent elements from receiving these events as well. The fewer restrictions you place on your code the more flexible it will be to maintain.
stopPropagation()
Sometimes you just want to stop the propagation. Take the following example:
<div class="post">
Normal text and then a <a href="/path">link</a> and then more text.
</div>
Now, lets pretend we want one thing to happen when you click anywhere in the div except on the link, and you want the user to actually be able to follow the link if they click on it. (From a usability standpoint, this is a poor example. You probably don’t want something else to happen if a user slightly misses clicking on the link!)
$("div.post").click(function () {
// Do the first thing;
});
$("div.post a").click(function (e) {
// Don't cancel the browser's default action
// and don't bubble this event!
e.stopPropagation();
});
In this case if we had used return false the div’s click event would not have fired, but the user would also not have been directed to the correct destination either.
stopImmediatePropagation()
This method stops any further execution of an event, even to other handlers bound on the same object. All events bound to a particular item will fire in the order they were bound. Take the following example:
$("div a").click(function () {
// Do something
});
$("div a").click(function (e) {
// Do something else
e.stopImmediatePropagation();
});
$("div a").click(function () {
// THIS NEVER FIRES
});
$("div").click(function () {
// THIS NEVER FIRES
});
If you think this example looks contrived, it really is. However, the situation is a very real one. As you build more abstracted code, different widgets and plugins may be adding events to the same code you are working with. This makes understanding and using stopImmediatePropagation worth while when you come across a situation that needs it!
return false
Only use return false when you want both preventDefault() and stopPropagation() and your code can support not canceling the default behavior until you reach the end of your callback execution. I strongly encourage against using this method in any examples you may write for new jQuery developers. It promotes a poor use of event cancellation and should only be used when you are consciously deciding you need what it provides..
Top, Bottom or Somewhere in the Middle
Before, when you were (mis)using return false, it always had to go at the end of your function, or at least at the end of a particular line of logic where no further execution was needed. With e.preventDefault we have more choices. It can be called at any time during a callback function to take effect. So where should you put it?
1. During development, it should (almost) always be the very first line. The last thing you want is for your form you are trying to AJAXify to actually submit to another page while you try to debug a JavaScript error in the callback.
2. In production, if you are following progressive enhancement, put it at the bottom of the callback, or at the end of execution flow. If you are progressively enhancing a normal page, then your link click event or form submit event has the proper server side fallbacks needed for browsers that don’t support JavaScript (or don’t have support enabled). The benefit here, however, is not related to browsers with JS turned off, but rather browsers with it turned on in the situation where your code throws an error! Take a look at the following code:
var data = {};
$("a").click(function (e) {
e.preventDefault(); // cancel default behavior
// Throws an error because `my` is undefined
$("body").append(data.my.link);
// The original link doesn't work AND the "cool"
// JavaScript has broken. The user is left with NOTHING!
});
Now, lets take a look at the same event with the preventDefault call being placed at the bottom:
var data = {};
$("a").click(function (e) {
// Throws an error because `my` is undefined
$("body").append(data.my.link);
// This line is never reached, and your website
// falls back to using the `href` instead of this
// "cool" broken JavaScript!
e.preventDefault(); // cancel default behavior
});
The same applies for form submit events as well, provided you have the proper fallback information in place. Never count on your code always working. It is far better to plan for a nice fallback than assume errors will never occur!
3. In production, if the functionality is JavaScript only, keep the call on the first line. Remember, it doesn’t necessarily have to be the first line in the function, but it should come as early as fits with your program logic. The concept here is this: If this part of your functionality was added with JavaScript in the first place, then a fallback is not really as necessary. In this case, having it first will just ensure random # characters don’t appear in the URL or cause the page to jump around. Obviously, provide as much error handling as needed to ensure your users aren’t left with nothing for their efforts!
Conclusion
I hope this article presented enough information for you to make the right choice when you cancel events. Remember to only use return false when you really need it, and make sure you cancel the default behavior at the right location in your callback. Always work to make your code as flexible as possible, and stop using return false!
Doug Neiner is an Editor at Fuel Your Coding and an official member of the jQuery Team. He is addicted to new technology, and specifically loves spending time with WordPress, Ruby on Rails and jQuery. Learn more via twitter or his Google Profile.


was this article inspired by that “how well do you know jquery” poll that made the rounds last week? I saw this usage of return false; in there, had no idea people did that. good explanation of why it’s a bad idea.
No, though I do remember seeing it in that quiz. It was inspired when I started to think about the fallback needs and implications of where you put preventDefault. Then it was compounded by seeing code around the web where return false is used all the time. Sometimes topics sit in my head for a while before I get them out on “paper” :)
Good article thanks. A good reminder of why return false is bad. Maybe some jQuery plugin writers could take not, this way plugins would play better together.
(off now to correct my jQuery plugins as I am sure return false is still in some)
Thanks Doug!
Or should I say aaaahhhh bummer. I now realized I have been using return false WRONG every time I have written it lol. Thank you for the explanation here, very helpful and I have seen the error of my ways. ;)
These are the standard JavaScript events. You also forgot the IE methods:
e.cancelBubble = true;
e.returnValue = false;
Hey, thanks for stopping by! The jQuery event functions are named the same as normal JavaScript events, however they are supported cross browser. There is no need to use any specific settings for IE as jQuery takes care of normalizing those for you.
Good article. The part about about adding more onto the click event for the parent div really hits home about return false. I knew the difference between the two, but this explains why I would use one over the other.
The Top, Bottom, MIddle thing helps too.
Loved you article. I’ll be sure to pass along the tip
I am guilty, I do this quiet often.
Thanks for straightening me out!
Never again…
Same here. Gonna refactor some code and take more caution next time.
Great article!
Yeah, will practice more caution here too. But I must admit when a deadline is nearing, sometimes hell breaks loose and discipline somehow jumps out the window..Then it’s the wild, wild west type coding. LOL!
Thx for straightening this out. I do disagree on that you should use fallbacks in case of a bug in the event handler. It makes both the code and the behavior of the application more complex, which obscures the bug and even increases the chance of making a bug in the first place. And changing code between development and production phase also is asking for new bugs. I’d rather spend some more time on good cross-browser testing before going to production.
Well, the point was if you *already* had a PE fallback in place that you were building on top of. If there is already a fallback, why would you want to intentionally prevent the default behavior, regardless of the success of your code? No amount of browser testing is going to reveal that one edge case you didn’t plan for and then a user is left with an unusable form/link that throws a JS error and dies.
As far as moving the call around, its not as difficult as it sounds. It doesn’t have to be part of your build script or anything. You just move it once you feel you are done with the main functionality. If during further development you see your fallback is being used, you move it back to the top to troubleshoot. Its a very one-off thing, and obviously has a higher benefit on a form vs. a link.
Good summary of the issue. Makes you wonder why jQuery decided to have return false stop propagation. I don’t know if they have an official stance on that.
I’m not an uber hacker like you guys, but not using return false and covering my bases seems like it would complicate matters more than necessary. Just being honest. It was interesting to see what return false was doing though. I didn’t know that stuff existed. Sorry for noobing up your post.
I totally understand the idea of doing what is simple and works. At least you will now think about it a bit more, and if you run into one of the roadblocks from using return false, at least you will know where to look to fix the problem!
Great article, return false became much clearer to me now.
Thanks for this great article, concise and easy to understand. I was having a problem using the jQuery validate plugin prior to submitting a form via Ajax, but the form wouldn’t submit via Ajax, kept using the default action and doing a page refresh. This was still the case when using preventDefault() instead of return false in the form submit event. The only way I have been able to prevent it from doing the default action was by placing action=”javascript:return false;” in the form markup itself? Any ideas?
Hi David.
I too have similar issues. e.preventDefault() did nothing for me on my form submit button click handler. I *have* to use “return false;” at the end of the function (after I’ve called .ajax).
As an aside, I’m having a lot of issues with jQuery Mobile (R1.0). Despite the books I have, the dozens of articles I’ve read, and days and days of tedious experimentation, I still do not understand various aspects of the framework. Most sources say it’s all simple but for me it’s all inconsistent and has become way to hard for the average programmer like me. DOM bubbling and lots of other behind-the-scenes goings-on just make it way to hard to figure out what on earth is going on most of the time.
Good luck if you want to do anything but the absolute basics with this framework.
Should these toggles really be links that go nowhere? I was under the impression that people just used links as buttons so that styling is easier in old browsers where :hover only worked on links. Think about it: do we really still need the href=”#” hack? Unless it is progressive enhancement where the fallback is a link to a page, I would say the example use case is wrong on a whole different level.
Didn’t even know that. Will rework old issues.
Thanks
Thank you for this Douglas.
This will help me debugging return false; issues easily in future but I will start using e.preventDefault more, it is much more neater.
I was a victim of those tutorials; I had no idea I was doing it wrong. Thanks!
Wow!!! This article is great!!! Congratulations…
Great article… a must read for even intermediate jQueryers. But to a certain degree, you may be promoting even more bad practices. If you are assigning events to objects AND their children/grandchildren, then you are unnecessarily creating more event handlers than you need. An even better practice would be to tie an event handler to the parent, and use the event object to determine what target was clicked… and in such case, “return false” would most likely be the preferred action.
I realize that my suggestion is a little out of scope for this article… but you accuse developers of learning things the wrong way while you yourself are using examples that are just as bad practice as using “return false” everywhere.
Hey Ryan! Thanks for taking the time to share your thoughts! One of the goals of writing JavaScript should be to write loosely coupled code. That means the widget/plugin that cares about the click event on the “a.button” selector is not necessarily the same code that cares about a click fired on the parent. In this case it would be creating tightly coupled code to do otherwise.
I suppose in certain event types (only mouse move, in, out events come to mind) the performance benefit would be worth the increased obscurity to attach a single event to the parent and manually test. But with those events, there is no point in calling return false since there is no browser default behavior associated with them.
My advice in the article it to stop mis-using return false. This implies there are a few cases where it is appropriate, but you need to know what is actually happening before you can make that decision. Most people use it willy-nilly without thinking of what is happening behind the scenes.
Thanks again for stopping by!
Very useful tip – I’d hope that this would be explained at a junior level, but I suppose it’s just easier to tell people to use return false.
Cheers Douglas!
Hi! Nice article. Consider me enlightened.
I came across this article when searching for a solution to a similar problem. I’m writing a plugin that has customer events. Naturally, these are triggered explicilty in the plugin code. The logic is such that the code may needs to terminate if a triggered event handler determines so, i.e. the plugin element logic is affected by another element that has an event handler for a plugin element. The old ‘return false’ seemed the closest way to do it, but we’re not talking about event propagation here. I’m currently using the .data method to pass the state, but I’m thinking there must be a cleaner solution. Ideas?
Hey there, thanks for this enlightning article.
But I am wondering how to use event.preventDefault() in the following example:
To get the respective panel open by clicking on an external link I used the following but it has the unwelcome drawback of jumping to the anchor. (didn’t find another way to get this to work):
$(document).ready(function () {
$(".accslide div").hide();
$(".accslide h3").click(function(){
$(this).next("div").slideToggle(1000)
.siblings("div:visible").slideUp(1000);
});
/*open respective anchor panel*/
hash = window.location.hash;
if(hash != 0)
{
$(hash).trigger('click');
}
});
I know this is neither a forum nor an Q & A blog but I would appreciate a comment on this.
The page where it is used:
http://www.sinitsa.de/content/Techniken.php
The external link comes from a gallery (clicking on the upper left “i” button and then on “Technik: Kreide” http://www.sinitsa.de/content/Kinder.php
Thanks for having may be a suggestion.
therealAnodyne
// This should do the trick
$(hash).bind(’click’, function(e) {
e.preventDefault();
}).trigger(’click’);
Thanky a lot Ryan for your suggestion.
Firefox and Opera handle it quite well putting the respective container in the middle of the window, which is not the worst thing to do. Chrome, Safari and IE 7 ignore the preventDefault function completely, how is that possible ?
Or did I put it in the wrong place ?
...
if(hash != 0)
{
$(hash).bind('click', function(e) {
e.preventDefault();
}).trigger('click');
}
...
Thanky again,
therealAnodyne
I revise, Chrome (Iron) doesn’t do it either. :)
Hey, therealAnodyn. The solution I gave you was sufficient and tested in all browsers. If it’s not working, then this is not the place to troubleshoot. There are entire websites set up just for solving problems like this, and a lot of the people reading this blog participate in those websites. Here are my favorites.
http://www.experts-exchange.com/
http://stackoverflow.com/
Of course you are right Ryan, this is not the right place.
I apologize and hope this small conversation won’t be considered spamming a blog’s comment section.
Thanks again,
therealAnodyne
Btw.: I inplemented your suggestion already and it does work in Opera, Chrome (Iron), Safari, Firefox (may be it was a cache problem) but defenitely not in IE7
Awesome article. Thank you. :)
Great to see what return false was actually doing. Thanks for laying it out with examples.
wow.. thanks.. i agree when u begin jquery, return false seems cool but when you start building complex apps the whole thing becomes flaky.. good job
Very good explanation!
Very useful article! I’ll apply the diferentiation in my next script.
Glad I stumbled upon this site.. good stuff. thx!
Okay, I’ll admit it. I’ve been doing it wrong. I promise I’ll stop now that I know. Thanks for the course correction.
You can get around the return false thing using jquery’s namespaced events which is what I tend to do when I’m adding click handlers to things that already have click handlers. The way I see it if something already has a .click() handler and you add another .click() handler the latter should overwrite the first one but that’s beside the point here. The following approach works:
$('a.button').live('click.myhandler', function(){ ... });or
$('a.button').bind('click.myhandler', function(){ ... });Thank you! return false; worked great on the desktop, but the iPhone web browser “ignored” it. I used preventDefault instead – perfect on both environments :)
Nice post, now i know why it’s bad to return false,
this article great, during the very first year of my JS coding life, I greatly misused return false;
eventually I realized, there must be a more elegant and precise way of canceling event actions, as at the time I don’t have a single clue about what return false does.
but then I met jQuery :P
Let’s see how can this bite one in real life, and it did bite me a few moments ago:) Assume you have a drop-down login box, which shows up when clicked on a button and hides when clicked on anywhere on the page but the box. Usual code (this one is actually from a high up-vote Stack Overflow answer):
$(document).click(function() {
$(”.loginBox”).hide();
});
$(”.loginBox”).click(function() {
return false;
});
The show/hide part works nicely, but you can no longer log in using that form, since your click on the submit button just can’t reach the submit button. Actually, even hitting Enter inside one of the text boxes doesn’t work. I don’t know the reason for this though, do hitting Enter in a textbox inside a form automatically translates into a click on the submit button?
Thank you, great article!
That’s just a bad approach, the trigger should use onBlur or loss of focus, then you don’t have to capture all clicks everywhere.
Great article. Thank you very much for this!
Thanks a lot.
Good input for someone like me who learnt it the wrong way :|
Hi Doug,
I cannot find a case where stopPropagation() is useful per se. Why will you have a clickable anchor inside a clickable div? What I mean is you cannot have nested anchors (html default clickable elements), then you shall not have 2 clickable elements one inside the other; am I wrong?
By the way, I was arguing with a coworker that has this same train of thought than you regarding this article, but there is no documentation about “please try not to use return false” inside jQuery Documentation. Why is this stuff posted in this blog, instead of inside the official website?
I’m not discussing about people misusing return false, but wondering:
a) What is the source for the correct “event driven inside jQuery”? (where was this taken from / explained on)
b) Are there real cases where we wan’t to stopPropagation() and not preventDefault() in order to choose this option against return false?
stopPropagation and preventDefault are not something implemented by jQuery, but are part of plain ‘ol JavaScript. So there is no “official site” per say that *should* explain this. It should just be part of your knowledge base… similar to how you understand closure, how to declare variables, and the difference between == and ===.
Real world scenario: So lets say you have a slider where each slide contains a large background image with some text and hyperlinks. If someone clicks on the slide, you would like to show a fullscreen version of the image. However, if someone clicks on one of the hyperlinks inside the slide, you want the browser to redirect to that page instead of displaying the fullscreen content. In such a case, you would attach a click event handler to the hyperlinks within the slide and prevent the event from bubbling up to the slide container by using preventDefault().
Doh, last word of my “real world example” should be stopPropagation(). My bad.
UX concern: I don’t think a user who clicks in a tout and gets a big image, will click again to check if the text was a hyperlink, or either will differentiate it is indeed.
I didn’t know it was part of old JS. Touché.
Trust me, stopPropagation was included in JavaScript for very good reasons… and there are very good real world situations where you want to use it:
http://dimsemenov.com/plugins/royal-slider/
Take note of the button and the fact that you can’t drag the slide when your mouse is over the button. stopPropagation at work.
I will continue to use return false, you just have to know what it does.
I don’t think I’ve ever relied on bubbling; despite not being really useful to me, it may get pretty intensive for the user if you have a deeply nested set of elements to check.
Stopping propagation may be desired as well as prevent default.
And I see two problems with your code (performance-wise):
- Everytime you use $(”something”) you’re calling a function which has to check what you’re telling. I know it’s easy to forget $ is a function while using jquery, but you’d better cache those selectors.
- In five years I’ve never attached more than one event per type to a selector.
Why would you want to make it fire two functions simultaneously?
Just use one.
I agree with you in most of things, but there are cases for event bubbling. There are lots of, if you think about using jQuery as framework, despite de UI components.
Nice article. Thank you.
How can one leverage the ability to pass arguments to an onclick handler and get the event? For example:
What’s the best-practices approach to passing custom arguments to handlerTwo
…and cancelling the click event from propogating and calling handlerOne?
This is really awesome. Thanks for the information dude.
Hi.., Please see the following link and tell me whats wrong in code..? http://stackoverflow.com/q/11257128/1482889
awesome article man!
Thank you fuelyourcoding! This is tremendously helpful.
Thanks for the information… nice explanation
Thank you. It’s very helps to me.
Yes, I had same issue form onward I need to observ in my code as usually I remember whenever I face this issue I was using
event.stopProppogation();
return false;
Don’t know why but unless I use these statement It wasn’t not working for all
browser I did already some searching on this. But first time I found good answer on this.
Thanks :)
I’ll be happy if you explain why this situation comes.