Beautiful CSS3 buttons with SASS

I had a very pleasant experience yesterday of making some nicely styled buttons with no background images, just pure CSS, using SASS to help me. What i’m about to share is by no means new or innovative, but i was impressed by it, so i decided i would write about it.

SASS = Syntactically Awesome Stylesheets

SASS is CSS styling for programmers. As programmers, we are basically lazy. We hate repeating ourselves. If we can find a way of making our lives easier, we will take it. I really like SASS for its mixin capabilities and colour manipulation, which i will demonstrate here.

Rails 3.1 Asset Pipeline

I’m really enjoying Rails 3.1 because it makes using SASS so simple. You add any files you like (CSS, SASS, SCSS) into app/assets/stylesheets and it compiles them all up into one CSS file. On a production server it minifies it too. It does similar magic for javascript files, which you’re now welcome to write in the very brilliant CoffeeScript. I love it!

So, then, buttons!

Let’s start with a nice HTML5 nav element containing a few links we want to turn into buttons.

<nav>
  <ul>
    <li><a href='/carrots'>Carrots</a></li>
    <li><a href='/pineapples'>Pineapples</a></li>
    <li><a href='/ginger'>Ginger</a></li>
  </ul>
</nav>

So this is what we start with:

Basic list alignment

First of all, let me do some basic manipulation to remove the bullet points and line them up side by side. Notice how with SASS (or SCSS) you can nest CSS definitions very nicely.

nav {
  ul {
    list-style-type: none;
    padding-left: 0;

    li {                                                                                                                                       
      float: left;
      padding: 0 5px;
    }   
  }
}

Add a background colour

It would be really good if these buttons had a background colour, say something very fetching like purple. While i’m here i’ll also change the text colour to white, make the text a bit bigger, and bold, and add some padding.

nav {
  ul {
    list-style-type: none;
    padding-left: 0;
  
    li {
      float: left;
      padding: 0 5px;
  
      a {
        background-color: #618;
        font-size: 1.1em;
        font-weight: bold;
        color: #fff;
        padding: 4px 16px;
        text-decoration: none;
      }
    }
  }
}

The neat thing about SASS is we can start to take this styling out into a mixin module:

@mixin button-style($base-color) {
  background-color: $base-color;
  font-size: 1.1em;      
  font-weight: bold;     
  color: #fff;
  padding: 4px 16px;     
  text-decoration: none; 
}

nav {
  ul { 
    list-style-type: none;
    padding-left: 0;   

    li {
      float: left;
      padding: 0 5px;    

      a {
        @include button-style(#618);
      }
    }
  }                                                                                                                                            
}

Rounded corners

Now obviously, buttons need rounded corners, don’t they! I can write a mixin for that:

@mixin rounded-corners($radius) {
  -webkit-border-radius: $radius;
  -moz-border-radius: $radius;                                                                                                                 
  border-radius: $radius;
}

@mixin button-style($base-color) {
  background-color: $base-color;
  font-size: 1.1em;
  font-weight: bold;
  color: #fff;
  padding: 4px 16px;
  text-decoration: none;
  @include rounded-corners(5px);
}

Box shadow

A bit of subtle shadow lifts the buttons off the page a bit:

@mixin box-shadow($h, $v, $radius, $spread, $color) {
  -webkit-box-shadow: $h $v $radius $spread $color;
  -moz-box-shadow: $h $v $radius $spread $color;
  box-shadow: $h $v $radius $spread $color;
}

@mixin button-style($base-color) {
  background-color: $base-color;
  font-size: 1.1em;
  font-weight: bold;
  color: #fff;
  padding: 4px 16px;
  text-decoration: none;
  @include rounded-corners(5px);
  @include box-shadow(1px, 1px, 3px, 0, #333);                                                                                                 
}

Text shadow

Some text shadow could also be quite nice. Notice as i’m going along i am building up SASS mixins that i can easily use in other places.

@mixin text-shadow($h, $v, $radius, $color) {
  text-shadow: $h $v $radius $color;
  filter: dropshadow(color=$color, offx=$h, offy=$v);
}
  
@mixin button-style($base-color) {
  background-color: $base-color; 
  font-size: 1.1em;
  font-weight: bold;
  color: #fff;
  padding: 4px 16px;
  text-decoration: none;
  @include rounded-corners(5px);
  @include box-shadow(1px, 1px, 3px, 0, #333);
  @include text-shadow(1px, 1px, 2px, #000);                                                                                                   
}

Gradient and colour manipulation

Now here’s a clever trick. To make the button more 3D i can apply a gradient, using a lighter version of the base colour that was passed in. Here SASS becomes really helpful.

@mixin linear-gradient($from, $to) {
  background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from($from), to($to));
  background-image: -webkit-linear-gradient(top, $from, $to);
  background-image:    -moz-linear-gradient(top, $from, $to);
  background-image:     -ms-linear-gradient(top, $from, $to);
  background-image:      -o-linear-gradient(top, $from, $to);
}

@mixin button-style($base-color) {
  background-color: $base-color;
  font-size: 1.1em;
  font-weight: bold;
  color: #fff;
  padding: 4px 16px;
  text-decoration: none;
  @include rounded-corners(5px);
  @include box-shadow(1px, 1px, 3px, 0, #333);
  @include text-shadow(1px, 1px, 2px, #000);
  @include linear-gradient(lighten($base-color, 10%), $base-color);                                                                            
}

A sneaky little tip: reverse the gradient on hover. It gives a tactile feedback. You could also darken the box shadow if you wanted a different effect.

The hover gradient reverse made me realise that the buttons could do with a slight border. I’ll use 10% darker than the base colour. I’ll give a 1px border, but 2px or even 3px would also look cool, for a really bold effect.

@mixin button-style($base-color) {
  background-color: $base-color;
  font-size: 1.1em;
  font-weight: bold;
  color: #fff;
  padding: 4px 16px;
  text-decoration: none;
  border: 1px solid darken($base-color, 10%);                                                                                                  
  @include rounded-corners(5px);
  @include box-shadow(1px, 1px, 3px, 0, #333);
  @include text-shadow(1px, 1px, 2px, #000);
  @include linear-gradient(lighten($base-color, 10%), $base-color);

  &:hover {
    @include linear-gradient($base-color, lighten($base-color, 10%));
  }
}

Imagine you are hovering over the carrots button:

Inner glow

To show a different effect, you could inset the box shadow with a lighter colour to give a highlight. You can have two box shadows, but it’ll clutter up my mixins, so i’ll leave you to figure that out on your own if you want both the highlight and the shadow.

Oh, i’ve increased the border and the rounded corner radius to emphasise this effect:

@mixin inset-box-shadow($h, $v, $radius, $spread, $color) {
  -webkit-box-shadow: inset $h $v $radius $spread $color;
  -moz-box-shadow: inset $h $v $radius $spread $color;
  box-shadow: inset $h $v $radius $spread $color;
}

@mixin button-style($base-color) {
  background-color: $base-color;
  font-size: 1.1em;
  font-weight: bold;
  color: #fff;
  padding: 4px 16px;
  text-decoration: none;
  border: 2px solid darken($base-color, 10%);
  @include rounded-corners(7px);
  @include text-shadow(1px, 1px, 2px, #000);
  @include linear-gradient(lighten($base-color, 10%), $base-color);
  @include inset-box-shadow(0px, 1px, 2px, 0px, lighten($base-color, 50%));

  &:hover {
    @include linear-gradient($base-color, lighten($base-color, 10%));
  }
}

The triumphant finale

I now have some button styles that i can apply wherever i want them. Because i used SASS to manipulate the colours, i only need to pass the base colour and it will apply a nice gradient, borders and glow.

So still without changing the original HTML, i can do this:

@mixin green-button {
  @include button-style(#152);
}

nav ul li:first-child a {
  @include green-button;                                                                                                                       
}

And you see, i now have a green-button mixin that i can happily apply to any link i want to! This is why i like SASS: it turns styling into programming! :D

I should say, i know these aren’t the prettiest buttons. I am more interested in the technique than the design, and i’m making them less subtle than they would ideally be, to prove the effect. When i figured out these techniques this week i was privileged to work from a gorgeous design by John Ryan, and the results turned out much prettier than these! :)

Resources

Here are a few useful resources to do with CSS3 and button generations:

Advertisements

2 comments on “Beautiful CSS3 buttons with SASS

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s