Taking a Button from PSD to HTML5/CSS3 using SASS
This article is about several things. Primarily, it is about how to realize a button design using the latest web technology available to us. The resulting button is progressively enhanced so that it looks okay in IE 7, a little bit better in IE 8, great in IE 9, and fantastic in all modern browsers. (Yes, IE 9 isn’t modern by my standards)
[Note: this article went long. The story of the IE "mutation" will happen in a follow up post.]
Also, I’m going to use SASS to create the CSS for this button. There are many timesaving features of SASS and that is a secondary theme of this post. You can learn about SASS here: http://sass-lang.com. I can’t recommend it enough. It actually renewed my love for web development.
I recently created an HTML5 site for a client. They needed some help and in particular, they were trying to match the button design as close as possible. There were a few goals:
- Match the design.
- The markup should be simple.
- No images!
- IE 9, 8, and 7 support. :/
That last one a tall order! Fortunately, they were fine with progressive enhancement under IE which meant that things would look similar, but not pixel perfect. So let’s see what we had to do…
Here is the original button design:
Before we can start to build this button in HTML, we need to understand how it is built visually. Let’s zoom in on the PSD to get a closer look. Hover over (or tap) the image to see the critical design elements…
To describe this button we have:
- The background color of the button is a solid orange. I.e., there is no gradient.
- Rounded corners of about 4px
- A darker orange 1px border (stroke)
- An inner shadow that gives a highlight, but it isn’t on every edge
- A faint text shadow of about 2px blur
- A faint drop shadow on the entire button of about 2px blur
Looking at this shopping list of CSS3 features, I can tell already that we are going to be hurting on all versions of Internet Explorer except the unreleased version of IE 10. Bummer.
…or maybe not… I know there are a few things we can hack to make IE work. But first, let’s get the easy stuff out of the way and make this button work for Safari, Chrome, and Firefox.
We start with a basic link and then use CSS3 features to style it according to our list. Here is our starting markup:
<a href="#" class="button">Clickity Clickity</a>
(For this example, I am using >a< because the markup is simple. But this will also work with input buttons.)
Let’s setup our SASS file, we need to include the CSS3 mixins:
The @import declaration simply brings in a standard library that is packaged with compass and SASS. It gives us a bunch of time saving goodies so that we can do things like write:
+single-box-shadow(rgba(0,0,0,.25), 0, 2px, 2px)
Instead of this:
-moz-box-shadow: rgba(0, 0, 0, 0.25) 0 2px 2px; -webkit-box-shadow: rgba(0, 0, 0, 0.25) 0 2px 2px; -o-box-shadow: rgba(0, 0, 0, 0.25) 0 2px 2px; box-shadow: rgba(0, 0, 0, 0.25) 0 2px 2px;
Time savings, yes? It doesn’t stop there. Did I mention you should go look at http://sass-lang.com?
Now, let’s work down that list of attributes. We need to have padding and margin on this button. That means the default display of a link needs to be changed from inline to inline-block. There is also significant amount of padding, so we will add that in. Let’s specify a font-size of 16px so we aren’t relying on body copy size which can change without us knowing. If we left the font-size as is, the text of the button wouldn’t be vertically centered when we apply this style to our input buttons. To vertically align, we give it a line-height of 22px. Here is our class so far:
@import "compass/css3" .button display: inline-block padding: 7px 24px 8px 24px font-size: 16px font-weight: 400 line-height: 22px
Here is our button so far:
Not very interesting…
Moving on, it would just look weird if our button ever wrapped to multiple lines of text. So, let’s fix the whitespace with nowrap. Further, we need to make sure the text is centered and because this is an <a> tag, we need to remove the text-decoration.
Our design calls for white text and an orange background color of #f38f01. Zoomed in, we see that the 1px outline of the button is a dark orange #c87704.
@import "compass/css3" .button display: inline-block padding: 7px 24px 8px 24px font-size: 16px font-weight: 400 line-height: 22px whitespace: nowrap text-align: center text-decoration: none color: #fff !important background-color: #f38f01 border: 1px solid #c87704
How does that all look under our test browser?
A pretty, plain, orange rectangle. Now, let’s add the “shiny”.
We need rounded rectangles, shadow on the text, a highlight shine on the top and left sides, and a drop shadow under the button. A white inset shadow will be used for the “shine” on top & left sides. A feature of CSS3 shadows that let us specify multiple shadows to apply. We will use this to specify both the drop shadow and shine of the button at the same time.
@import "compass/css3" .button display: inline-block padding: 7px 24px 8px 24px font-size: 16px font-weight: 400 line-height: 22px whitespace: nowrap text-align: center text-decoration: none color: #fff !important background-color: #f38f01 border: 1px solid #c87704 +border-radius(4px, 4px) +text-shadow(rgba(0,0,0,.5), 1px, 1px, 3px) +box-shadow(rgba(black,.3) 0px 1px 1px, rgba(white,.25) 1px 1px 0px inset)
(You can see that special SASS syntax we are using again: +border-radius and such.)
In the last line, the first shadow is the the drop shadow, and the second is the white shine. Here we go:
Finally, we need the button to reflect a change in its state. When a mouse hovers over, let’s lighten it a bit. And when someone clicks or touches it, let’s make it darker.
@import "compass/css3" .button display: inline-block padding: 7px 24px 8px 24px font-size: 16px font-weight: 400 line-height: 22px whitespace: nowrap text-align: center text-decoration: none color: #fff !important background-color: #f38f01 border: 1px solid #c87704 +border-radius(4px, 4px) +text-shadow(rgba(0,0,0,.5), 1px, 1px, 3px) +box-shadow(rgba(black,.3) 0px 1px 1px, rgba(white,.25) 1px 1px 0px inset) &:hover background-color: #ff9c0e &:active background-color: #da8001
Okay, how does it look in Safari compared to the original PSD?
Wow, that’s not bad at all! Firefox is the same. Let’s check Chrome and… ruh roh! Take a look:
Chrome actually renders fonts differently then other browsers. Type appears at what seems like one weight lighter (400 to 300, in this case). So we are going to adjust that here:
// Chrome renders font one weight lighter than every other browser. // Their text shadow also appears to be a bit darker, though that could // be because of the step up in font weight .chrome .button font-weight: 700 +text-shadow(rgba(0,0,0,.40), 1px, 1px, 3px)
Since discovering this font “bug”, I’ve started the practice of tagging every page body with a .chrome class if that browser is being used. Yeah, I know, don’t target browsers… Well, someone get Google to fix it and we can stop that…
Let’s see where we stand in Safari, Chrome, and Firefox:
Damn, that is spot on!
Okay, now that sinking feeling in your stomach is the realization that we are only 10% of the way done. I.e., we still need to fix IE. I’ll cover that out in a follow-up blog post.
The title of this post includes the buzzword, HTML5. Though, not a single HTML5 tag was used in the making of this button. Sorry about that. For those seeking the “truth”, know that the polish of this button was derived entirely with CSS2 and 3 features.