Quick Tip: Prevent Animation Queue Buildup
read 63 commentsYou've probably stumbled upon a navigation powered by some jQuery effects during your web adventures. Of course you then ran your mouse back and forth over the navigation really fast to watch the animation repeat itself over and over and over again.
The natural queuing of animations/effects by jQuery makes the typical animation super easy to code and move on to more important tasks. However, sometimes the animation queue just gets in the way.
Here is an example of a navigation that has some effects applied to it via jQuery. Mouse back and forth over the links to see how the animations build up.
Here is the JavaScript that does the effect for the menu:
Now let's look at how we can prevent this undesirable behavior. Ready? Simply call the .stop() method before animating again. Here is the updated JavaScript that fixes the animation queue buildup by using the .stop() method.
Here is the navigation again, using the above JavaScript.
As you can see, the animation is no longer queued up by moving your mouse back and forth over the menu items.
You can even get bonus points for implementing something like the hoverIntent plugin that can add a slight delay before running the animation. Doing so makes sure the animation plays only if the user actually places the mouse on the element.
For more information about the .stop() method, visit the jQuery documentation page. To see a real-world example of the .stop() method in action, using its two arguments — clearQueue and goToEnd — check out the script Karl Swedberg put together at Little Orange Star.















Simple and incredibly effective; thanks!
Helpful article Brandon, thanks!
Another variation is to just use the stop() on the first (mouseover) function of hover() and not on the second (mouseout) function. Depending on what it is for, it can help smooth out the animations some.
I just tried Eric's suggestion of just using one stop() on the first hover() and it doesn't work for me. Still get a bad buildup if I don't use stop() on mouseover and mouseout. Just FYI
I struggled with this yesterday. Woke up this morning and saw this post. Thanks!
this article is too old! you don't need another plugin to stop the queue... just use queue:false in animate function...
sample code:
However, I still couldn't find a way to stop the queue for fadeIn/fadeOut type of events...
You wouldn't believe the myriad elaborate ways i've circumvented animation queue buildup in the past. This is a great little tip, as it's so simple yet so entirely unobvious to new jQuery users.
Simple but very nice effect, thanks...
Great tip!! Succinctly and ease of use , thanks!!
I'm having this very problem with a slider/AJAX app I am building. The slider sends the value to a PHP script to be calculated and then returned, but when I move the slider, it queues up the script every split second, and it takes a while for the values to catch up to the slider. I tried implementing the stop() method as shown here, but I don't think it works for my app. Here is the URL - http://mclindigital.com/tests/calculate.php.
@ mikemick
I wont comment on why you need to goto the server to do this however what you could do is implement a setTimeout on the ajax call. You can then cancel the timeout if the slide method is called again before the timeout period expires.
quick demo (un-tested) http://pastebin.me/49771a088320e
@redsquare
Thank you for the quick response. Yeah, this is a very simple example of what I am trying to do. Eventually this (among other UI elements) will use the PHP script to dynamically sort a recordset from a database. When I pasted your code, nothing came up in the browser window. I am assuming a syntax error? Anyways, this should put me on the right path. Thanks for you help.
when I said "sort" I meant "filter" a record set from a database
@ mikemick
Ah ok I understand now! Yeah my code was untested but if you put your stuff live I'll debug any issues.
Got it working now. I think you had forgotten the "}" before the ", 200);" on line 18. Thanks for you help.
That solved the exact problem I was having with a tutorial I'm writing. Thanks you!
After running into this problem numerous times I'm glad to finally see a solution. Nice job!
Great article man!
Great and simple trick for preventing buildup. Thanks for that.
However, I did pick up on one little quirk. Not sure if it's a typo on your part or a misunderstanding on my part but the function as you have it listed:
I use this on my website and it works fine:
Am I missing something or did you just mistype the "left" part?
Thanks!
No typo, I just animated the position instead of animating the padding like you did. It probably would have been a better choice to animate the padding!
One other thing, Shane: The reason it probably works for Brandon but not you is that animating the
leftproperty requires the element to be positioned, e.g.position: relativeorposition: absolute. If your element hasposition: static(which is the default for HTML elements), then it remains ... static.Yep, you're absolutely right Karl. I set the positioning in my blog and now just using "left" works. Thanks for the clarification. I'm still using "paddingLeft" because it keeps the link from moving out from underneath the mouse, but it's good to know the "why" of it.
if I move mouse cursor to the space between left border and Menu, it will unlimit reload. how to prevent it. it looks only occur on Firefox.
The behavior you are seeing is because I animated the left property of the li element. By doing so I'm actually moving the link out from under your mouse. I should have just animated the padding instead of the position.
I use the hoverIntent plugin for hover related events, but this is cool for the animate() method.
How do you do to get easein to work with animate? I have downloaded jQuery UI with Select all components but it dont work
works if I remove
, "easing": "easein"but it works if I include jquery.easing.min.js shouldn't it work whit jquery-ui-personalized-1.5.3.min.js"Extends the internal jQuery effects, includes morphing, easing and is required by all other effects."
You might want to try the jQuery UI 1.6rc6. You might also want to check the names of the easing methods. I think the names of the easing methods changed.
Thanks Aaron.
You were right they had changed the names of the different easing's.
Thanks for cool tutorial. I just re-write this tutorial in my site with Indonesian language.
Check it out http://achmatim.net/2009/02/02/efek-animasi-sederhana-pada-menu-dengan-jquery/
That is really cool! Thanks for doing that.
Actually I liked first example. It's kind of cool effect :-)
Viktar, it is a cool side-effect. I had a similar side effect where LI items would open top and bottom. Looked neat until the lower LI items would just bound, and bounce, and bounce. Ugly. This fixed it nicely.
wow,
very nice..
Can you please show me the entire html, css and JS for that.
if its fine with you..
Thank you very much for this easy solution. I was having the exact same problem in my custom navigation.
Awesome! You just saved my day :-)
Great article Brandon. However, I am having a problem implementing this technique in some of my code. I have a span element within a td element and wish to animate the span when the td is hovered over (making a tool tip, essentially). I am selecting the span using the find() method. The stop() method is not having any effect and my animation queue is still building up. Any ideas on why using the find() method is affecting this? Javascript below:
Cool story--thanks!
stop() only seems to deal with the "animation" queue--what if I have a .hover() set up with a simple show/hide toggle in the functions? I have this same issue with excess events queuing. Is there a way to deal with this?
Nice. I somehow 'needed' to know how to do that. I have a site where buildups like this should be stopped. Good thing I looked in here ;)
This is perfect!! I've been moaning about this animation build up for ages. I really like a fade effect I have on my site, and almost removed it right before i found this. Thank you, and it was so simple too.
Hi,
I sometimes even use "stop(false, true)" to make sure that all works nice.
Janis
И всё таки вы написали..
This solved my opacity show hide animation issue.
Awesome article. I knew just where to put this to use in an older project. I'm kind of a stickler for perfect and here's an issue that I'm having: If I hover real fast over each item with the .stop() in use it will move just 1mm out and then move back. It makes it looks a little jittery. I'm thinking one way this can be stopped is if we could somehow tell the Jquery first wait half a second, then move the item to the left 20px, then move it back immediately when the user leaves the mouse. That way if someone were frantically hovering over each item they wouldn't get that immediate movement and jittery look.
Are you following me? I apologize if that were hard to explain. One question to sum it up: Is there a way to tell JQuery to wait half a second before actually moving the item to the left 20 px?
Thanks All!
Dan B. Lee
You'll want to re-read the second to last paragraph where I mention using the hoverIntent plugin to do just that. :)
Hi,
is there a similar effekt for Picture slidein/out?
stopping sliding works like a pausing i think...
Lol now that's insanley easy and effective you made my day =)
I came to another solution - the hoverFlow plugin:
While the stop()-method prevents animation queue buildup, it introduces another problem: When you do a fast mouseover/-out, you will see no animation at all or just a part of the animation. This behavior seems somehow unnatural.
In my opinion, a single (and fast) mouseover/-out should result in a full animation cycle. The classical hoverIntent-plugin can't help here since it does the exact opposite: Triggering the event after a longer timespan.
Ideally, all animations should only play if they correspond with the current (that is, when the animation is dequeued, not when the event was triggered) mouse position. A mouseover animation will only run if the mouse is currently over the element, and a mouseout animation will only run if the mouse is currently not over the element. Otherwise, the animation queue is emptied.
The hoverFlow plugin does exactly that! The easiest way to compare the different approaches is to have a look at the plugin homepage:
http://www.2meter3.de/code/hoverFlow/
HTH
This achieves a similar effect to the hoverFlow plugin (still some cuts if you go nuts with the mouse):
Hello. Just learning jQuery and this issue has been driving me nuts. I am aware of Hoverflow, but it seems like I should have been able to get stop() to work for the simple dropdown menu I was creating with slideDown/slideUp. The problem I was having was mentioned above...
Basically, if you move the mouse over a bunch of times, the animation starts only triggering a little but not completing until it stops happening at all. I fixed this by setting the gotoEnd to True, but then I ran into an issue where if I hover off and then back on it endlessly flashes from being animated to nothing. After a bunch of trial and error here was the perfect solution :
It seems no stop on the mouseout WITH gotoEnd set to true fixes it perfectly.
Jason,
Your example was similar to my own situation in building a nav using one unordered list nested within a parent unordered list .
My original source of inspiration in building my navbar is from
designreviver
Building off of that I used your example provided. To add some animation and fix the hover error. Everything works perfectly in IE (amazing!), but every version of FF I've tested in will fire a "display" on the first hover. Then on the second hover it works fine with slideDown and slideUp.
Here is my js...
Any suggestions on how to fix this for FF? Or am I missing something?
Thanks!
nice... Simple and super effective thanks, man!
thanks jason , i had same problem.
Great post, thanks! I recently ran into a problem in IE6/7 that I was able to fix this way.
I had an animate on hover for an image which was suffering from the same chaining effect mentioned here if the user moused over multiple times.
The following stops new events entering the queue until all current events havefinished executing. This works better than stop() as it allows the animation to complete. If the user triggers a new animation to fire and the queue is not empty the function simply returns.
e.g. call it at the start of your hover function.
$(".button").hover(function(){
// drop new animations for this element
if ($(this).queue("fx").length>0){return}
//do animations
});
On second thought, for a menu you'll need it to be a bit more complicated such as interrupting the menu slide gracefully on a new mouseover.
Hoverflow seems to do this nicely as someone else has mentioned but it didn't work for me when chaining 6 animations on an image (I was making it bounce).
But manipulating the queue is definitely the way to go. A simple stop() is a little too dramatic for my liking.
Here's another example which is almost there but is still a bit jerky. http://buildinternet.com/2009/01/how-to-make-a-smooth-animated-menu-with-jquery/
Hi Brandon,
I have setup a simple hover background fade within a list of links (vertical sub-navigation), I have used jquery.color.js with the example code below:
var originalBG = $("#nav-sublinks li").css("background-color");
var fadeColor = "#F4F5FF";
$("#nav-sublinks li").hover( function () {
$(this).stop().animate( { backgroundColor:fadeColor}, 750 )
},
function () {
$(this).stop().animate( {backgroundColor:"#E3E4EE"}, 450 )
}
);
It works...but intermittently the hover state will stay on once the mouse has moved to another link. Do you know why this is happening?
Thanks a lot for this article!
I just started looking for solution to prevent animation escalation.
It's a big surprise for me that solution is so simple :)
it'S official: This is my personla blog post of the month… Thank yu very, very much!
What's the difference between this solution and using queue:false in the animation options?
Thanks,
Andrea
Thanks.. this is not just a quick tip but also a really great simple tip :)
great job, I've been saved :)
This was exactly what I was looking for. Thanks a bunch.
Helpful article. Thanks!
Thanks so much! This fixed a frustrating problem I was having. I have status messages shown in divs at the top of my page, which are hidden automatically after a certain time period. They also have a button close them prematurely. I was using a dummy animation to show them for a certain amount of time and then I was fading out and removing the divs. The problem was that if I clicked the close button, nothing would happen because it was put in the queue after the dummy animation. Adding stop before the fadeout on the close button click fixed it.
Thanks!