Another Solution to Animation Queue Buildup in jQuery

Or: Why do hover animations continue after I stop hovering?

Over at learningjQuery.com, Brandon Aaron published a quick tip on how to prevent animation queue buildup in hover animations. Since I was not satisfied with his solution, I tried to find another.

After taking some wrong paths and learning a lot about jQuery's animation (queue) system, I think I finally found a good solution.

The last locigal step was to wrap it up into a nice jQuery plugin - and so hoverFlow was born.

Download hoverFlow
2.25 KB, minified 1 KB

The API is similar to jQuery's own animate()- method and uses the same definition of animation parameters, durations and options.

However, the hoverFlow()-method additionally requires an event type to be its first argument.

jQuery('#selec.tor').hoverFlow(eventType, params, [duration], [easing], [callback])

jQuery('#selec.tor').hoverFlow(eventType, params, options)

As always, the jQuery-method should be called when the DOM is ready.

Find more examples and usage notes on the demos page. I've also made some examples for using hoverFlow with sub menus.

hoverFlow is tested in Firefox 2+, Internet Explorer 7+, Opera 9.6, Chrome 1. I've seen it working (slowly) in IE6, but who cares...

The plugin requires jQuery 1.2.3 or higher (since it uses the data()-functions).

hoverFlow is dual-licensed under the GPL and MIT licenses. Feel free to modify the source to your needs.

Do you have any suggestions, found bugs, or patches? Drop me a line.

hoverFlow is a jQuery plugin by Ralf Stoltze, 2meter3.de.

The Problem

Mouseover/-out the menu a couple of times. After you stop moving the mouse, the animation will continue since you've built up the animation queue with every mouse event.

$('.example1 .anim_queue_example a')
  .hover(function() {
    $(this).animate({ left: 20 }, 'fast');
  }, function() {
    $(this).animate({ left: 0 }, 'fast');
  });

The Quick Tip using stop()

The quick tip from learningjquery.com uses the stop()-method to prevent animation queue buildup.

While this helps solve the initial problem, it introduces another: When you now do a fast mouseover/-out, you will see no animation at all or just a part of the animation. This behavior seems somehow unnatural.

$('.example2 .anim_queue_example a')
  .hover(function() {
    $(this).stop().animate({ left: 20 }, 'fast');
  }, function() {
    $(this).stop().animate({ left: 0 }, 'fast');
  });

A Solution - The hoverFlow plugin

The plugin honors a single mouseover/-out with a full animation cycle while preventing animation queue buildup.

A queued animation will only run if it corresponds with the current mouse position at "runtime". That is, 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 empied. More demos...

$('.example3 .anim_queue_example a')
  .hover(function(e) {
    $(this).hoverFlow(e.type, { left: 20 }, 'fast');
  }, function(e) {
    $(this).hoverFlow(e.type, { left: 0 }, 'fast');
  });