Did you know it’s possible to make links that shake when you hover on them, with pure CSS3? Nor did I, until today!
So, this is another one of those things to file in the “Totally useless, except for impressing your geek friends” category. Links (or, in fact, any elements) that shake when you hover on them. Or, you know, just shake anyway, if you leave out the :hover part.
Before we start, a challenge: 1st Prize goes to anyone who can work this into a paying client’s project, 2nd Prize goes to anyone who can find a way to use this … anywhere. Convincingly, I mean.
Without further ado, the demo:
CSS3 Shake Animation Demo (Webkit only)
Pretty neat, right? So, how’s it done?
CSS3 Webkit Animations and Transforms
I’m not going to go into detail about how CSS3 animations work – that’s been covered in extensive detail for the past couple years, so if you’re totally clueless, read up a little, or just copy and paste regardless!
The best thing about CSS3 animations (esp. on hover) is that they degrade pretty much gracefully – instead of seeing the animation between the default and hovered state, an old-fashioned user just sees the standard hover state. So, if you make something expand and rotate on hover, a non-Webkit user would just see it pop out, without animating to it.
I mean, sure, we developers go a little overboard sometimes, and so a non-Webkit user (having not seen the smooth transition) might well wonder how the hell that innocent little image turned into a gigantic porno dragon riding a Harley, when hovered – but let’s face it, non-Webkit users aren’t going to miss much with these ultra cool CSS3 shaking links.
Enough Small Talk
Without further ado, some CSS:
@-webkit-keyframes spaceboots {
0% { -webkit-transform: translate(2px, 1px) rotate(0deg); }
10% { -webkit-transform: translate(-1px, -2px) rotate(-1deg); }
20% { -webkit-transform: translate(-3px, 0px) rotate(1deg); }
30% { -webkit-transform: translate(0px, 2px) rotate(0deg); }
40% { -webkit-transform: translate(1px, -1px) rotate(1deg); }
50% { -webkit-transform: translate(-1px, 2px) rotate(-1deg); }
60% { -webkit-transform: translate(-3px, 1px) rotate(0deg); }
70% { -webkit-transform: translate(2px, 1px) rotate(-1deg); }
80% { -webkit-transform: translate(-1px, -1px) rotate(1deg); }
90% { -webkit-transform: translate(2px, 2px) rotate(0deg); }
100% { -webkit-transform: translate(1px, -2px) rotate(-1deg); }
}
.shake:hover,
.shake:focus {
-webkit-animation-name: spaceboots;
-webkit-animation-duration: 0.8s;
-webkit-transform-origin:50% 50%;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
}
.shake {
display:inline-block
}
So what’s going on here? Allow me to elaborate, old chum.
NB: Even if you grok webkit-animations completely, keep reading as there’s some important stuff underneath viz using this.
As I said, much of this will have been covered in the excellent resources linked to in the opening paragraph, but here’s a rundown:
@-webkit-keyframes [animation name]
This is an ‘@’ declaration, much like @font-face or @media, but is proprietary to the Webkit rendering engine – like everything else in here. Inside this rule, you have your stages (keyframes) for the name animation. You can have two keyframes, 0% and 100% (start and finish), for example, but I’ve declared ten steps, each 1/10th of the animation. The speed of the animation is unimportant in this – you’re just describing the timing percentages, and applying CSS styling to those specific keyframes.
-webkit-animation-name / -webkit-animation-duration
The first applies the animation effect to the current selector you’re writing a rule for, in this case, I’m telling it to use the animation ‘spaceboots’ (the very same boots these links will be shaking in, later on.)
The animation duration, well, that’s pretty simple. Using ‘s’ (seconds) as the units, if you set the duration to 1s, then the 40% { } keyframe will activate at 0.4s, etc. etc.
-webkit-animation-origin
This one takes the same syntax as background-position – for example, -webkit-transform-origin: [left] [top] – and so 50% 50% dictates that the origin position for these transforms (the up/down/left/right and rotations) should come from the very centre of the element. If you were to set this to 0 0, or 100% 100%, you’d see different effects. go on, try it – I dare you.
-webkit-animation-iteration-count / -webkit-animation-timing-function
… should be fairly self-explanatory. -webkit-animation-iteration-count: 1 / 2 / 200 / infinite, whatever you like. We’ve chosen infinite, because we want those links to just keep on a-shakin’.
Timing function is the same as easing – I’ve used linear, because, hell, you wouldn’t be able to see a bezier curve in effect at this speed – and linear is probably faster in performance terms (though I have no evidence of this.)
Shake ‘em please:
So the .shake class is given :hover and :focus treatment, so that if a user focuses on the link (by tabbing), it will still shake. That should be everything, except that these -webkit-transforms will not apply to inline links, sadly, so they need to be either display:block or inline-block.
I’ve set them to inline-block, so they don’t disrupt paragraphs, but you could use either really (just make sure that if they’re blocks, they’re either floated or have a specific width, otherwise they’ll be 100% width and thus shake kinda funny.)
You could also switch the .shake CSS declaration for the following code, which basically allows you to style other elements (like divs or images) with the CSS3 .shake class, while still having display:inline-block on shaking links and other selected shakey inline elements (e.g. <span class="inline shake">):
.shake {
display:block;
position:relative;
}
a.shake,
.shake.inline {
display:inline-block
}
Did I mention you can apply this code to anything? You could also lose the :hover and :focus pseudo-classes, to just have elements that just shake, forever. I can’t imagine why you’d want to – like a lot of CSS3 techniques, really!
Ready Links? Start shakin’.
So, now you’ve got the code, why not see if you can use it?
Like I said at the top – 1st Prize goes to anyone who can work this into a paying client’s project! Comment below and let me know how you get on, or if you’re able to use this to create any other, cooler effects :D
Much love, Joss

I converted this to a ‘heartbeat’ which I use when hovering above a button… Slick!
@-webkit-keyframes thumb { 0% { -webkit-transform: scale(1); } 50% { -webkit-transform: scale(0.9); } 100% { -webkit-transform: scale(1); } } .backbutton img:hover { -webkit-animation-name: thumb; -webkit-animation-duration: 200ms; -webkit-transform-origin:50% 50%; -webkit-animation-iteration-count: 2; -webkit-animation-timing-function: linear; }That’s awesome! Nice work dude!
Thanks, getting my feet wet :)
I think that WordPress uses the same technique on the newest version of self-hosted wordpress. If you have that installed and updated to the current version, then go to your http:// www. myDomain .com/wp-admin page and type in an incorrect username and/or password. When you press login, it will reject your credentials and the whole login box will shake along the x-axis. It only works in webkit browsers so I think it is the same effect. I suppose I could dig into the source code since it’s open source, but I don’t feel like it.
Anyway, very cool tutorial.
Thanks! I believe WP login uses a jquery shake animation, but ditto – I haven’t checked personally.
I’m going to step up and claim that prize :)
I was able to work this onto my employer’s homepage, for the month of September anyway. The little idol-guy in the banner graphic gets his jiggy on when you hover.
It was pretty fun, and the graphic artist that did the images was more than thrilled with the effect. Thanks for the idea/code!
I used this in a Northwestern Football PhoneGap app. On a page that has a png of some keys, I added an accelerometer watch so that when the user shakes their phone, the CSS animation is added to the keychain image and a key jingle sound plays. It’s a tradition, they jingle keys during kickoff.
It’s going to be a free app, so I’m not contending for the paid client thing :] Good work on getting someone to pay for it; that heartbeat thing sounds cool too.
Thanks for the code, it worked great!
Nice!
I included the app link. Thanks again.
Any help to make this work on Mozilla?
@deko: All of this code works in Firefox 10 if you replace -webkit- with -moz-. I haven’t tested on earlier versions but I’m pretty sure this stuff should work a couple of versions back as well.
Incorporated into a paying client’s website – the company name is SocialBuzzar, with buzz in red. I did the whole package – brand identity + website design, and they were happy with the end result. Will link when the site is done hosting. =)
Fantastic – can’t wait to see it!
Pingback: Implementing CSS Grids into Your Drupal Website
Used for a paying client :) Check it out live at http://hayleydoyle.com on the phone at the bottom of the homepage and the client write up at http://nuvu.co.za/clients/hayley-doyle. Code slightly adapted to show more vendor prefixes (-moz, no prefix)… anyone know any more that can be added?
Cant tell how old all these comments are as there are no dates on here, but I plan on using this in quite a few instances on a clients site, will update later. Is there any solution to have this display on non-webkit yet?
Thanks!
Pingback: Managing the Little Things: Changing Cursors Through CSS.
Thanks a looot my friend!!!
Just used this animation at my new site http://creativorama.com. Thanks a lot!
Thanks for the awesome tutorial! I used it on a site I am currently developing.
Het! I added this to the facebook login button of my site,
Do you think I should only apply in hover status?
thakns for sharing
Pingback: Ten Smooth-running Webkit CSS Animation Examples | CSS Animation Studio