(Update – 22nd February 2012 – I’m no longer using this on my site. The effect described should still work, but I’m not sure it was a particularly good idea in the first place!)
As I was putting my site together, I was looking for a nice mouse-over effect for the main navigation links, something a bit different.
I came up with an idea for a sort of ‘wobble’ effect that would repeat while the mouse is over a link (as seen in the clouds above). I was just getting started with learning jQuery, so thought I would attempt to use it to produce the wobble.
I’ll explain the code I came up with below.
The Code
First, some HTML that I’ll use to demonstrate:
<div id="wobble">
<a>Link 1</a>
<a>Link 2</a>
<a>Link 3</a>
<a>Link 4</a>
</div>Nothing too complicated. Now, some CSS:
#wobble a{
position:relative;
top:0;
margin-right:10px;
}position:relative is required as the wobble effect changes the position of the link relative to its original position. Without position:relative, nothing happens.
There is a strange problem that occurs only in Opera with this effect, where the link jumps to the top of the page then back down again when the mouse moves over it, top:0 seems to fix this.
margin-right:10px is just to seperate the links out a bit, it isn’t required for the effect to work.
Essentially, the wobble effect is just an animation between two positions, in this demonstration between top:2px and top:-2px. The jQuery animate function is perfect for this. Here’s the wobble function I came up with:
function wobble(e, amount){
$(e.target).animate({top: amount + 'px'}, function(){
wobble(e, -amount);
});
}I’ll explain this bit by bit:
function wobble(e, amount) is the function declaration. e is the event that occured to trigger the wobble effect (the mouse moving over a link, which I’ll explain soon). amount is the number of pixels that the link should move.
e.target tells us which link the mouse moved over, so therefore which link to animate.
The first paramater of the animate function ({top: amount + 'px'}) tells jQuery which CSS property to animate and to what value.
The second parameter (240) is the number of milliseconds the animation should take to complete.
The third parameter is a callback function, which is called when the animation has completed. In this case, it just calls wobble again, but this time passing -amount, which swaps amount from positive to negative and vice-versa each time the function is called.
You must put the call to wobble within an anonymous function, or wobble will be called immediately rather than at the end of the animation, resulting in all sorts of nasty errors.
So this…
function wobble(e, amount){
$(e.target).animate({top: value + 'px'}, wobble(e, -value));
}… won’t work.
wobble isn’t much use at the moment. However, the jQuery hover function in which mouse-over and mouse-out behaviour can be defined, allows us to use it to create the desired effect.
Here’s the hover function I used:
$('#wobble a').hover(function(e){
//mouse over
$(this).stop().animate({top: '-2px'}, 120, function(){
wobble(e, 2);
});
}, function(){
//mouse out
$(this).stop().animate({top: '0'}, 120);
});#wobble a means that the mouse-over and mouse-out behaviours within the hover function will apply to all the a elements within the element with an id of wobble (in the demo HTML from earlier).
Line 3 starts off the animation when the mouse is moved over a link (this refers to the specific link), in the same way as in the wobble function explained before, but as it is starting from top:0 rather than top:2px or top:-2px the animation only needs to take half as long (120 milliseconds). Then wobble is called as the callback function, therefore starting off the repeating animation.
Notice that e (the event) is passed to wobble so that it knows which element to animate via e.target.
Line 8 moves the link back to it’s original position (top:0).
The stop() function clears the animation queue, which prevents the link wobbling about for ages if someone moves the mouse backwards and forwards over the link really fast in a short space of time.
Of course, you can go from here to style things however you like. Or you could change how far the link animates by changing amount, or change how long the animation takes.
To Conclude
So, there you go, a fairly simple wobbly link effect using jQuery.
As I said, I’m fairly new to jQuery, so there may be better / different ways of doing this. Also, I certainly wouldn’t use it for every link on a site, as I imagine it might get quite annoying, but for a few select links or other elements I feel it works quite well.
It also degrades nicely, so if somebody has JavaScript turned off, or it isn’t available, the links will still function perfectly well.
I loved the simplicy of your tutorial, very well apreciated. I’m also getting my hands dirty with Jquery. Thanks
I tried to replicate exactly this into Jsfiffdle, but the animation seems a little different as the one demo on the page. It goes up once and sticks. Maybe I’m missing something? This is the link: http://jsfiddle.net/YHyaD/6/
Hi Francis,
Apologies for the delayed reply.
The JavaScript section of the code from JSFiddle is missing the
wobblefunction, which is required for the animation to loop correctly. The code in the JavaScript box on JSFiddle should be as follows:Ross.
Very well apreciated. I missed that one. Great script.
Ross,
I’m trying to aplpy the wooble to a set of images which have a particular class assigned to them.
I tried adjusting the jquery function, css and html to work with class. Sorry still newbie.
http://jsfiddle.net/YHyaD/9/
Hi Francis,
You will need to adjust the jQuery selector, so that it finds the correct elements in your HTML. Also, the CSS rule is not being applied correctly (again, because your HTML is different from my original example).
Here’s a forked jsFiddle that should work: http://jsfiddle.net/WBSaQ
Notice the differences in the first line of the JavaScript, and the first line of the CSS.
I hope this helps!
Ross.
http://jsfiddle.net/YHyaD/11/
It works on images now. JSfiffle does give this error with JSLINT:
Error:
Problem at line 11 character 16: ‘wobble’ was used before it was defined.
function wobble(e, amount){
Implied global: $ 1,3,8,12
Hi again,
If you swap around the code slightly (so that the ‘wobble’ function is defined before it is called), as follows, JSLint should be happy:
Ross.
Thanks for this simple tutorial I can now start wobbly with the jquery.
Hey this is great! One question though – it runs much smoother on your site than even my plain html document, and hovering over both uses approximately the same CPU. Is it possible you used different, perhaps better, values in your header than the ones you used in the example?
Hi Julian,
Sorry for the delayed reply.
As far as I can tell (it’s been a long time since I looked at this!), the code I’ve used is pretty much the same as the example, so I’m not sure what could be causing the difference. Do different browsers show the same difference in smoothness?
Ross.