Create GitHub-Style Buttons with CSS and jQuery, MooTools, or Dojo JavaScript

By  on  
GitHub Buttons

I'm what you would consider a bit of a GitHub fanboy. We all know that GitHub is the perfect place to store repositories of open source code, but I think my love of GitHub goes beyond that. GitHub seems to understand that most repo sites are usually boring so they've spiced their site up with some catchy CSS and great JavaScript features. One tiny piece of the GitHub design I love are the basic buttons. Lets examine how we can create our own GitHub-style buttons with a bit of HTML, CSS, and JavaScript.

The HTML

<!-- button 1:"plain" -->
<a href="javascript:;" class="minibutton"><span>Basic Button</span></a>
<!-- button 2:"icon" -->
<a href="javascript:;" class="minibutton btn-download"><span><span class="icon"></span>Button With Icon</span></a>

Below are two styles of buttons: one basic button and one with an icon to the left of the text.

The CSS

	/* button basics */
	a.minibutton {
		display:inline-block;
		height:23px;
		padding:0 0 0 3px;
		font-size:11px;
		font-weight:bold;
		color:#333;
		text-shadow:1px 1px 0 #fff; 
		background:url(http://github.com/images/modules/buttons/minibutton_matrix.png) 0 0 no-repeat;
		white-space:nowrap;
		border:none;
		overflow:visible;
		cursor:pointer;
		text-decoration:none;
	}
	
	a.minibutton>span {
		display:block;
		height:23px;
		padding:0 10px 0 8px;
		line-height:23px;
		background:url(http://github.com/images/modules/buttons/minibutton_matrix.png) 100% 0 no-repeat;
	}
	
	a.minibutton:hover, a.minibutton:focus {
		color:#fff;
		text-decoration:none;
		text-shadow:-1px -1px 0 rgba(0,0,0,0.3);
		background-position:0 -30px;
	}
	a.minibutton:hover>span, a.minibutton:focus>span {background-position:100% -30px;}
	
	a.minibutton.mousedown{background-position:0 -60px; }
	a.minibutton.mousedown>span{background-position:100% -60px; }
	
	/* with icon */
	a.btn-download .icon {
		float:left;
		margin-left:-4px;
		width:18px;
		height:22px;
		background:url(http://github.com/images/modules/buttons/minibutton_icons.png?v20100306) 0 0 no-repeat;
	}
	a.btn-download .icon {background-position:-40px 0;}
	a.btn-download:hover .icon, a.btn-download:focus .icon {background-position:-40px -25px;}

The CSS is bountiful but it usually is when trying to achieve perfection. And just like most buttons, the GitHub button is an A element with a series of SPAN elements inside of it. You'll also note more CSS code is needed to accommodate for the button...obviously.

The MooTools, Dojo, or jQuery JavaScript

/* MooTools (FTW) */
window.addEvent('domready',function() {
	$$('a.minibutton').addEvents({
		mousedown: function() {
			this.addClass('mousedown');
		},
		blur: function() {
			this.removeClass('mousedown');
		},
		mouseup: function() {
			this.removeClass('mousedown');
		}
	});
});

/* Dojo Toolkit */
dojo.addOnLoad(function() {
	var buttons = dojo.query('a.minibutton');
	buttons.connect('onmousedown',function() { dojo.addClass(this,'mousedown'); });
	buttons.connect('onblur',function() { dojo.removeClass(this,'mousedown'); });
	buttons.connect('onmouseup',function() { dojo.removeClass(this,'mousedown'); });
});

/* jQuery */
jQuery.ready(function() {
	jQuery('a.minibutton').bind({
		mousedown: function() {
			jQuery(this).addClass('mousedown');
		},
		blur: function() {
			jQuery(this).removeClass('mousedown');
		},
		mouseup: function() {
			jQuery(this).removeClass('mousedown');
		}
	});
});

GitHub gets it right by making the JavaScript portion only serve as an enhancement for button focus/mousedown. This JavaScript is not required.

In the end, the amount of CSS and JavaScript used is probably more than you would have thought but the result is really smooth. Feel free to profess your own love for GitHub below.

Recent Features

  • By
    Regular Expressions for the Rest of Us

    Sooner or later you'll run across a regular expression. With their cryptic syntax, confusing documentation and massive learning curve, most developers settle for copying and pasting them from StackOverflow and hoping they work. But what if you could decode regular expressions and harness their power? In...

  • By
    Responsive and Infinitely Scalable JS Animations

    Back in late 2012 it was not easy to find open source projects using requestAnimationFrame() - this is the hook that allows Javascript code to synchronize with a web browser's native paint loop. Animations using this method can run at 60 fps and deliver fantastic...

Incredible Demos

  • By
    MooTools TwitterGitter Plugin

    Everyone loves Twitter. Everyone loves MooTools. That's why everyone should love TwitterGitter, a MooTools plugin that retrieves a user's recent tweets and allows the user to format them however the user would like. TwitterGitter allows the user to choose the number of...

  • By
    Style Textarea Resizers

    Modern browsers are nice in that they allow you to style some odd properties.  Heck, one of the most popular posts on this blog is HTML5 Placeholder Styling with CSS, a tiny but useful task.  Did you know you can also restyle the textarea resizer in WebKit...

Discussion

  1. The final result is awesome. But yeah, the amount of CSS and JS was way bigger than i expected :O

    But it’s worth the result. Thanks for sharing David ;)

    Regards

  2. Very nice.

    They need an active state though.

    I never used to have them, but there is very good cause for using them. The hover says there is action here. The active shows that you are activating it.

  3. Ronny

    As Adam is saying, I would use :active for the mousedown part. No need for JS here David!

  4. There seems to be a little bug…once the button has been clicked, it cannot be clicked again without clicking elsewhere on the page…? Firefox 3.6.3

  5. The “:active” part would be a good fallback. GitHub uses JavaScript so there must be some rational behind it. I’ll do more research…

  6. Kostas

    I think it’s IE that does not support the “:active” pseudo class

  7. @Adam, @David: Actually we most definitely support an active state. Hence the javascript for mousedown (click and hold on a button to see). The reason that I used javascript instead of the :active pseudo class is that the pseudo class continues to stay activated long after you’ve released your mouse button.

    For example, using active and doing: click on a button, click the back button -> arrive on a page where :active is still activated and your button is in a depressed state even though it should be back to it’s normal state. This is only true for links (IIRC) and not for .

    Maybe just the perfectionist in me, but that’s why I chose to use mousedown rather than :active.

  8. @Kyle Neath: Thanks for following up Kyle. Nice work too! :)

  9. @Adriaan:

    Yup I agree the button does get stuck in the down position in FF…

    Another bug is the active/mousedown state is not working in IE or Chrome.

  10. @Adriaan, @B. Moore: I’ve changed “focus” to “mousedown” an for maximum compatibility.

  11. Metric Stormtrooper

    nothing says “THIS SITE IS HTML5!!!” better than using a javascript framework to change background-images at a:hover / a:active :)

  12. @David Walsh: you da’MAN!

    thank you

  13. @Metric Stormtrooper: Are you high?

  14. @Kyle Neath: roflmao!! may be its the dark side of the force skewing whats left of his brain…..

    :P

  15. Technically, you could do all of this without any nested spans, js, or images (other than the icon) by using pseudo-elements, border-radius, and gradients or box-shadow…but obviously you’ll end up with different appearances in less capable browsers.

  16. @Kyle Neath, David: Weird. On gitHub im getting no active state. And in this example, im getting a stuck active state if you decide to click but not release on the button (something a user may do if at the last second they decide to not go through with it.)

    Im in Safari 4.0.5 – 10.6.3

  17. @Adam: I don’t do support requests through blog comments (I find these are people who generally are doing things like disabling javascript).

    But if you click and hold (without ever releasing) you will most definitely get an active state as you should. All buttons in all OSes behave in this manner.

  18. this buttons are great!

  19. Cambazz

    Hello,

    These buttons are sure nice, but I would like to know more about the buttons that you used in this blog, like the reply, post comment, etc, the ones that look like facebook.

    If you could write a new posting about these, or point me in the right direction that would be great.

    Best..

  20. Nice effect. Thanks for the share.

  21. Tom

    These seem different in one way — if you click and then drag out and then release, the button is still dark but with black text. The fix for this is to also attach a “mouseleave” handler that removes the mousedown class. This works in jQuery for sure – I haven’t tested the others.

  22. Vish

    Might sound like a noob question, but how do I increase the size of the button?
    I tried increasing the height in the CSS code but that includes a different color when increased.

  23. how we can use it on INPUT BUTTON ?

    • hugemetalfan

      The fact that the button needs to be anchor and include a span tag in it – makes it absolutely useless. A button should be INPUT only. Bahhh, useless crap.

  24. Little bug. if you were to click on the button then drag your mouse off the button the release
    you will see the button go into “lock”

  25. I like these buttons a LOT, but — is there a way to do these so that they can be resized as the text on the rest of the page is resized (especially if you’re using ems to size your text)? And what about a button with two or three lines of text in/on it?

  26. This is fantastic. but I was wondering, stupidly so and because i’m quite tired lol, but the “mousedown” effect you’re adding is easy enough to make in plain ole JS? i design more than program so sorry for the stupidity of my question =)

  27. Ok, after some needed sleep I relented and took onboard the MooTools :) I would like to point out however your MooTools snippet above is missing Focus state and some other errors/changes. If you do use MooTools version copy it from the Examples source :)

    But thank you Mr Walsh fantastic little addition to my library :)

  28. Couldn’t you just use no javascript, and just style an a tag? And have the :active and :hover states for the same things you are using js for.

    • Just realized css gradients could make the code a lot shorter, too.

  29. You can fix the Firefox problems with the stuck active state like this:

    mouseup: function() {
    this.removeClass(‘mousedown’);
    this.blur();
    }

    not sure why blur: is able to successfully removeClass(‘mousedown’) and mouseup: isnt, but it works…also if you just use this.blur() it gets stuck in Safari, so use both and it works in everything!

  30. vino

    If anyone is interested the YUI3 lib version of the JS, I use:

    YUI().use('node', function(Y) {
    function mouseBIn(e) {
    var button = e.target;
    button.addClass('mousedown');
    }
    function mouseBOut(e) {
    var button = e.target;
    button.removeClass('mousedown');
    }
    var buttons = Y.all('.minibutton');
    buttons.on({
    mousedown: mouseBIn,
    blur: mouseBOut,
    mouseup: mouseBOut,
    mouseleave: mouseBOut,
    mouseout: mouseBOut
    });
    });

    I use both onmouseout and onmouseleave (forgot why – but I think some brws’ support one and others the other) to counter for the leave effect mentioned in above comments.

  31. Andrew

    I tried code above

    My text

    And the button does not close well.The left image has 2-3 pixel gap from the rest of button

  32. TeMc
    jQuery.ready( function(){ ...
    

    should be:

    jQuery.fn.ready( function(){ ...
    

    or

    jQuery(document).ready( function(){ ...
    
  33. Thanks for the tutorial. We used them here (http://www.skyrill.com/seatinghabits) and added a link to your page too.

  34. Excellent discussion, and great site, I find that I am here often these days.

    I wanted to add another button tool to the list that allows you to create 3 state buttons with only CSS. (no javascript, or plugins).

    Check it out here…
    http://dvia.com/buttonMaker

    The tool itself is pretty powerful and feature rich considering it is still in beta, but I hope to have 1.0 ready by years end.

    t

  35. it’s seems that we have problem with : http://github.com/images/modules/buttons/minibutton_matrix.png

    anyone here have the solution..?

  36. You should really have downloaded it rather than hotlinking as the original URL is no longer active.

  37. Jim

    can you provide the bakcround images as I really need them?

  38. I actually wrapped this up in a nice mooTools class for those of you using mooTools…uses the same image matrix and replaces on the fly all on the fly with these buttons, supports multiple button sizes, all css rollovers, and fixes the error with having to click elsewhere on the page…if interested let me know I will zip it up and write up documentation….

  39. Mike

    My code tag isnt displaying properly, it is input, type = button…the script automatically replaces all native buttons with these buttons and works perfectly in all browsers…anyways ill zip it up and post tomorrow i am sure someone will use it.

  40. Stephen

    http://davidwalsh.name/dw-content/github-button.php

    both buttons look the same… am I missing something?

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!