How to create Skype-like buttons using jQuery

March 11, 2009

 

If you use Skype I am sure that you noticed that animated button for adding more people to a chat. When you click on it the icon on the left “jumps” for a few times. I love that animation. And that’s why I’m going to show you how to create the same button using jQuery and some simple CSS.

View demo

If you are not sure what button am I talking about, image below might help you.

 

And this is how our button will look like:

Ok, the task here is quite simple – I want the icon to jump for a few times when I hover the button. (In Skype window this icon jumps when you click on it, but I think it would be much better to have it jump on hover)

The button itself consist of an image and text placed inside of a link.

<a class="button" href="#">
    <img src="button.png" alt="" />Send info</a>
    or <a href="#">cancel</a>

Let’s style the button. CSS code for this is simple and won’t go through all the classes here. The key is that the icon is absolutely positioned inside its relatively positioned container – the link. The position of the icon is set to simulate Skype button, and that is to cover the left side of the button. Please note that you will see the rounded corners on the button only in Firefox thanks to -moz-border-radius- properties.

.button {
    padding: 4px 10px 3px 25px;
    border: solid 1px #8AB134;
    position: relative;
    cursor: pointer;
    display: inline-block;
    background-image: url( 'bkg.png' );
    background-repeat: repeat-x;
    font-size: 11px;
    height: 16px;
    text-decoration: none;
    color: #40740D;
    -moz-border-radius-bottomleft: 5px;
    -moz-border-radius-bottomright: 5px;
    -moz-border-radius-topleft: 5px;
    -moz-border-radius-topright: 5px;
}
.button img {
    position: absolute;
    top: -4px;
    left: -12px;
    border: none;
}
.button:hover {
    color: #8AB134;

Now the animation. We have three jumps on original Skype button – one large and two small jump. In first jump, icon will go up for 6px, in second 3px and in the last jump 2px. After each jump, the icon will go back to its original position defined in CSS. I guess it is pretty much similar to the Skype button.

$(document).ready(function(){
    $(".button").hover(function(){
        $(".button img")
            // first jump 
            .animate({top:"-10px"}, 200).animate({top:"-4px"}, 200)
            // second jump
            .animate({top:"-7px"}, 100).animate({top:"-4px"}, 100)
            // the last jump
            .animate({top:"-6px"}, 100).animate({top:"-4px"}, 100);
    });
});

Code is tested in Firefox, Safari and IE7. If this doesn’t work in IE6, I simply don’t care.

The icon used in this tutorial is from Developpers Icons set. Now try the demo, download the source code and enjoy styling your new buttons!  

Let's discuss this on twitter.

78 Comments

  • Davide Espertini (March 11, 2009)

    Oh great sample Janko! Really cool button like Skype! :D

  • David Walsh (March 11, 2009)

    Great work! I love this!

  • Janko (March 11, 2009)

    Davide, David: Thanks!!!

  • thismat (March 11, 2009)

    I’m curious why you would go this route instead of a pure CSS solution?

    To avoid the extra class/css markup? Be a little more dynamic when adding new buttons?
    I can see both of those as valid solutions, but is there a usability hit if someone has no javascript?

    Good post, thanks!

  • thismat (March 11, 2009)

    Hmm, thinking about it…I don’t think there would be a performance hit, though I bet if this doesn’t work in IE, it can easily be fixed to, great solution!

  • Marco (March 11, 2009)

    That was pretty cute and works pretty nice. Although it doesn’t add anything functional, it does look pretty cool for the user.

    For this one, your tagline isn’t fully covered: It indeed is "good locking" but "functional"? Nah ;).

    Anyway, keep up the good work!

  • Janko (March 11, 2009)

    thismat: Sure, there won’t be any usability hits, it just won’t jump. It works in IE7, though. ;)

    Marco: Yep, this is just "good looking". Tagline is more like a summary of the entire content :D

  • Westley Knight (March 11, 2009)

    Love it! Gonna have to find some site where I can utilise this effect!

    My only issue with it is that the drop-shadow jumps with the icon, and you can see where it ‘cuts off’.

    Obviously this is my personal issue, I just can’t get myself past things that don’t react in accordance to the laws of physics! ;o)

  • Westley Knight (March 11, 2009)

    Oh, and I’m not from Romania and spelt my domain wrong!

  • peter (March 11, 2009)

    Tested this in IE6 and the bounce works, however the icon background is not transparent. I see a gray square that bounces.

    Should the bounce be extended to bounce on focus too? for keyboard users?

  • Someone (March 11, 2009)

    You may set outline:none to remove it in Firefox.

  • Gustavo (March 11, 2009)

    Some people just… grrr
    Caring about tagline? lol

    Good Work Janco! Keep going…

  • Brian Arnold (March 11, 2009)

    That’s a pretty neat trick. I’d change it slightly, though.

    Looking at your first jump, it’s called with .animate({top:"-10px"}, 200).animate({top:"-4px"}, 200) – but what happens if you decide you want to move your button’s top to -3 or -2? You suddenly have to adjust all six animation calls – unless you lean on the fact that jQuery does relative scaling too. =)

    If you change it to .animate({top:"-=6px"}, 200).animate({top:"+=6px"}, 200) it’ll now move up 6 pixels, then down six pixels, regardless of where you started. Straight from the jQuery API for animate:

    [quote]As of jQuery 1.2 you can now animate properties by em and % (where applicable). Additionally, in jQuery 1.2, you can now do relative animations – specifying a "+=" or "-=" in front of the property value moves the element positively or negatively, relative to its current position.[/quote]

    Your demo is leaning on jQuery 1.2.6, so relative adjustments will work wonderfully. They’re absolutely great, just as functional, and allow you to separate presentation from interaction just that much more. =)

  • Janko (March 11, 2009)

    Westley: Of course, I broke the laws of physics! This is functioning according to quantum physics :D Just kidding, you are right!

    peter: yes, sure, why not!

    "someone": Of course, I forgot that!

    Gustavo: Thanks!!!

    Brian: Good points, yes that’s more flexible. Thanks!

  • Mario Awad (March 11, 2009)

    I love it. Thanks :)

  • Moschos (March 11, 2009)

    Excellent, I launched Coda now to test it!! Keep up the good work informing about jquery,php etc!!
    Thanx

  • Ervin Ter (March 12, 2009)

    Very nice! Keep up the good work.

  • CyberFox (March 12, 2009)

    Very Nice!

  • Nokadota (March 12, 2009)

    This is cool, thanks for the tut.

  • Ricardo (March 12, 2009)

    I wonder if there’s a way to animate a gif using something like you did here… Make the gif shine a metallic glare just once when you pass over it (and only repeats if you pass over it once more).

  • Janko (March 12, 2009)

    Thanks guys!

    Ricardo: yes, you could do something like this. Check out this tutorial: http://snook.ca/archives/javascript/jquery-bg-image-animations/

  • Rob (March 12, 2009)

    really neat tutorial. something very cool i will definitely be "borrowing" in the future

  • L.M (March 12, 2009)

    Good Job, Guy.

  • senp (March 12, 2009)

    has a small problem with opera :(
    can’t use inline-block, change to block or add a block wrapper and use it as a pos:relative

  • Bill Lowden (March 12, 2009)

    Cool animation! Thanks for explaining it so well.

  • nemoprincess (March 12, 2009)

    Good Job! Thank you very much…

  • James Cready (March 12, 2009)

    -webkit-border-top-left-radius: 5px;
    -webkit-border-top-right-radius: 5px;
    -webkit-border-bottom-left-radius: 5px;
    -webkit-border-bottom-right-radius: 5px;

    Why you hatin’ on Mac?

  • ZeroDotNet (March 12, 2009)

    Excellent article!!

    Added to my "nice features" collection.

  • James Cready (March 12, 2009)

    A) You have 4 lines of CSS that could be summed up by: -moz-border-radius: 5px;
    B) You are ignoring Safari’s border-radius: -webkit-border-radius: 5px;

  • Janko (March 12, 2009)

    Thanks everyone!

    senp: Thanks for the opera tips!

    James: You are right, it’s not perfect. I assume you don’t like it then.

  • rubycat (March 12, 2009)

    I’m a dumba$$…it looks great but doesn’t actually work. Like, clicking on that sexy button doesn’t submit the form I’m using it on. Have I missed something obvious? I didn’t quite understand the reason for wrapping this all in a link and now am wondering if I misunderstood what this can be used for?

  • T-Law (March 13, 2009)

    Thanks ;) I threw IE6 :)

  • Kampanye Damai (March 13, 2009)

    Great, that’s all I need. I’m studying about jQuery, thanks.

  • Stephon Marbury Shoes (March 13, 2009)

    Hi Janko. thanks for sharing this coding. I want to try this skype button in my blog.
    thanks again.

  • Bilard (March 13, 2009)

    This is really great! Thanks!

  • Patternhead (March 13, 2009)

    Nice trick. jQuery rocks

  • terminator (March 14, 2009)

    whoow cool button , nice to look wiil be my blog widget
    thank you very much

  • De’Star (March 18, 2009)

    Awesome! It will complete my blog. Keep it up!

  • Caina (March 18, 2009)

    Greate!!

  • xaccrocheur (March 24, 2009)

    Hi all, nice reading, most notably about the webkit selectors (what is this non-standard nonsense ? One rule by browser ? feh) and Janko, your button is very nice. Only it errors in firebug, may be a PB w/ a new version of the main lib :

    handler is undefined
    trigger()()jquery-1….6.min.js (line 25)
    ready()()jquery-1….6.min.js (line 26)
    nodeName()()jquery-1….6.min.js (line 21)
    filter()()jquery-1….6.min.js (line 12)
    ready()()jquery-1….6.min.js (line 26)
    ready()()jquery-1….6.min.js (line 26)
    (?)()()skype_buttons (line 10)
    onreadystatechange()()jquery-1….6.min.js (line 27)
    onreadystatechange()()jquery-1….6.min.js (line 27)
    nodeName()([function()], function(), undefined)jquery-1….6.min.js (line 21)
    onreadystatechange()()jquery-1….6.min.js (line 27)
    [Break on this error] while(elem=second[i++])first[pos++]=elem…r)delete events[type][handler.guid];else

    ## (this from your demo page)

    g is undefined
    (?)()()jquery.j…e3Q%3D%3D (line 1)
    (?)()()jquery.j…e3Q%3D%3D (line 1)
    (?)()()jquery.j…e3Q%3D%3D (line 1)
    (?)()()jquery.j…e3Q%3D%3D (line 1)
    (?)()()jquery.j…e3Q%3D%3D (line 1)
    (?)()()jquery.j…e3Q%3D%3D (line 1)
    (?)()()dedie.ma…iva.co.ma (line 30)
    (?)()()jquery.j…e3Q%3D%3D (line 1)
    (?)()()jquery.j…e3Q%3D%3D (line 1)
    (?)()([function(), function(), function()], function(), undefined)jquery.j…e3Q%3D%3D (line 1)
    (?)()()

    ## (this from my own page)

    Thanks a lot !

  • Janko (March 24, 2009)

    xaccrocheur: you are right, but I really don’t know what is the problem :(

  • riant (March 26, 2009)

    So cool,Thanks for your share.

    By the way, I am a Chinese.

  • heh (April 6, 2009)

    dont u fink it iz indeed ratha stupid to say "i dont care" like a 4 year old?

  • Janko (April 6, 2009)

    @heh: Nope, I don’t think it’s stupid. Read the article.

  • Stas (April 6, 2009)

    Thnx, Great solution!

    ps: the code after "The button itself consist of an image and text placed inside of a link." has one unnecessary tag A (in the last line)

  • Hardy (April 8, 2009)

    That’s definitely a great idea I’m going to use in some of my next projects! TY fot that inspiration!

  • sachin (April 10, 2009)

    Good tutorial and really useful..thanks

  • riant (April 10, 2009)

    And I want to know, If I want to set buttons more then one in a page, what should I do? thank you.

  • Pintocas (April 10, 2009)

    That’s cool

  • lucapette (April 14, 2009)

    Simple and elegant solution, thank you for the job done. I think i could use it in the future.

  • Photoshop (April 14, 2009)

    Really cool trick

  • gentax (April 14, 2009)

    thanks so much, nice effect ;)

  • Alex (April 14, 2009)

    Why are you using nested links? Those JS errors are most likely caused by this blatant disregard to simple HTML rules :)

  • Alex (April 14, 2009)

    Never mind my last post – the demo itself is properly structured, but the HTML for the button on this page has an extra tag.

  • CoryMathews (April 15, 2009)

    This does not work in Opera 9.64

  • Janko (April 15, 2009)

    Thanks everyone!

    Stas: Thanks for letting me know, I haven’t noticed that – removed!

    riant: You just repeat the button as many times as you want on the page :)

    Alex: no problem, my mistake!

    CoryMathews: I have a bad habit not to test my demos in Opera :D Looks like the icon gets broken during animation.

  • Guta (April 15, 2009)

    Bravo Janko,

    Excellent "How-to" !!!

    Svaka cast!

  • Eric A. Maginniss (April 17, 2009)

    That’s a beautiful animation. The only problem that I can see with it (which happens with a lot of content using animations) is that it continues to stack animation events even as one is playing. If you run your cursor across the button 20 times quickly and then move it away, you will continue to see bouncing for several seconds. The best way to prevent this is to not append new animation actions while one is still playing.

    Thanks,
    Eric

  • Janko (April 18, 2009)

    Guto: Hvala!!!

    Eric: Absolutely true, I missed that. Thanks!

  • Toni (April 18, 2009)

    Hvala, hvala :)

  • Matthias (April 18, 2009)

    Simply nice! I like it. :)

  • Stefan (April 20, 2009)

    thx, i changed your js code to

    [quote]
    $(document).ready(function(){
    $(".button").hover(function(){
    $(this).children( "img" )
    .animate({top:"-10px"}, 200).animate({top:"-4px"}, 200) // first jump
    .animate({top:"-7px"}, 100).animate({top:"-4px"}, 100) // second jump
    .animate({top:"-6px"}, 100).animate({top:"-4px"}, 100); // the last jump
    });
    });
    [/quote]
    then it works with several buttons on same page

  • ahmedstudio (April 21, 2009)

    pls i wanna make this effect in button control in Visual studio 2005
    this code for button control

    <asp:Button ID="Button1" runat="server" CssClass="button" Text="Button" />

    who can i add icon pls any one tell me

  • Janko (April 22, 2009)

    Toni, Matthias: thanks!

    Stefan: Thanks for the snippet :)

    ahmedstudio: it should work with asp:button as well because it uses "button" class.

  • CssRain (April 28, 2009)

    good work。

    I do it like this.

    Link:http://www.cssrain.cn/demo/skypebuttons/SkypeButton2.html

    哈哈

  • Anderson Aguiar (April 29, 2009)

    Very Nice! Jquery r0x

  • zhang (April 30, 2009)

    Cool,I like it.

  • Steffi (May 2, 2009)

    This Butons looks very nice. I will make now someone, test and then customize them a little bit. Thx for this great helpfully post.

  • Avelino (May 8, 2009)

    Hi.

    I found a javascript error :

    Error : ‘guid’ is null or not an object.

    Anybody has found the solution?

    Thanks a lot.

  • awake (May 11, 2009)

    FYI… Does not work as it should on Opera

  • Keith D (May 18, 2009)

    I wasn’t sure what you were on about… Just looked at your demo and saw the animation.. great stuff, made me smile.

    These tuts are fantastic, clear and well set out plus the source code is always helpful.

    More jQuery please.

    Thanks.

    Keith D

  • Pablo (July 21, 2009)

    Love the effect. Subtle but adds a little wow! to the buttons. I’d like to see it animated through a parabolic bounce to make it more realistic but it’s a nice bit of inspirational design.

  • philip beel (September 17, 2009)

    Hi, really great idea!

    One suggestion tho. I noticed that if you repeatedly hover over the button the animate function stacks up. Not a big issue, but you could fix it pretty quickly by doing this:

    $(":not(:animated)", this).animate(…)

    Hope this helps,

  • Andreas (October 7, 2009)

    hello janko,
    great, that’s all I need. I’m studying about jQuery, Thanks.

  • Bryan (October 21, 2009)

    One thing I noticed was CssRain’s link works in Opera but it doesn’t reset itself to the original position.

    Other than that opera issue the original script is great.

  • Speller (October 24, 2009)

    i really like it and I’m gonna use it with philip bell small fix. Thanks

  • matt (December 14, 2009)

    as Eric had mentioned, the animation continuing is a little annoying, and fortunately, all you need is to add a stop() before you animate. nice tut though

  • dec (January 25, 2010)

    @senp "has a small problem with opera Frown
    can’t use inline-block, change to block or add a block wrapper and use it as a pos:relative"

    use ""display:block;float:left;" to sort the problem