Dynamic CSS3 Buttons with LESS

There’s been a lot of buzz surrounding CSS3 buttons – including some really great tutorials. The concept behind a basic button, however, is pretty simple:

  1. Apply a subtle background gradient
  2. Add some rounded corners
  3. Add text shadows – optionally
  4. Add a thin border – optionally
  5. Add a box shadow – optionally
  6. Repeat this process for active and hover states

For sure, making good buttons means doing these steps well. But programmatically, this is pretty damn simple. The difficultly lies in design not code.

With that in mind, let’s look at how we might use a CSS abstraction language, like LESS, to boil these steps down and make our button code super flexible. But first, let’s take a look at CSS abstraction languages more generally.

What’s a CSS abstraction language?

An abstraction language is a wrapper that adds powerful functionally to the standard CSS language. Have you ever wanted to set a variable in your stylesheet or do some math? Abstraction languages make this possible.

Now, if you’re like me, you might be thinking: “If I need to do multiplication in a stylesheet something’s gone terribly wrong.” Keep reading. Maybe you’ll change your mind.

How do I use a CSS abstraction language?

Normally, abstraction languages require a supporting back-end language. This supporting language parses your abstracted code and generates normal, static stylesheets at runtime. Ruby, for example, does exactly this to turn SASS into CSS.

That’s cool, but for most projects we don’t need a powerful back-end framework. And there’s certainly no reason start using one just to make your stylesheets more dynamic. This means, by and large, abstraction languages just aren’t viable except in large, complicated projects.

But LESS is about to change all that. Alexis Sellier has recently developed a pure JavaScript implementation. This means no back-end language is required. Just follow these simple steps:

  1. Give your stylesheet a mime type of .less rather than .css
  2. Add an attribute of rel="stylesheet/less" rather than rel="stylesheet"
  3. Include the less.js script below all stylesheets in your header.

With that finished, your header should include something like:

        <link rel="stylesheet/less" href="buttons.less" type="text/css" charset="utf-8" >
        <script src="less-1.0.30.min.js" type="text/javascript" charset="utf-8"></script>

And now we have access to some pretty awesome features. Like setting variables and performing operations:

        @pagewrap_width: 970px
        @accent_color: #2BBF26;        

        section {
          @pagewrap_width - 300px
          color: @accent_color - #f0f0f0;

And that’s just a few of the awesome features. I encourage you to checkout the details and documentation.

How can we use this to make better buttons?

1 Get a nice looking button.

Making a nice button can be tricky, so I recommend using the code posted in one of these excellent tutorials. But if you’d rather roll your own, I suggest this dead simple button making tool.

Whatever your method, just get some CSS and paste it into your LESS equipped stylesheet. In this example, I’ll be using this code:

        /* styles for button color */
        .button {
          color: #fef4e9;
          border: solid 1px #da7c0c;
          background: #f78d1d;
          background: -webkit-gradient(linear, left top, left bottom, from(#faa51a), to(#f47a20));
          background: -moz-linear-gradient(top,  #faa51a,  #f47a20);
        .button:hover {
          background: #f47c20;
          background: -webkit-gradient(linear, left top, left bottom, from(#f88e11), to(#f06015));
          background: -moz-linear-gradient(top,  #f88e11,  #f06015);
        .button:active {
          background: -webkit-gradient(linear, left top, left bottom, from(#f47a20), to(#faa51a));
          background: -moz-linear-gradient(top,  #f47a20,  #faa51a);

        /* basic styles for button size, padding, etc. */
        .button {
          display: inline-block;
          outline: none;
          cursor: pointer;
          text-align: center;
          text-decoration: none;
          font-size: @font_size;
          line-height: 100%;
          font-family: Helvetica, Verdana, Arial, sans-serif;
          padding: .55em 2em .55em;
          text-shadow: 0 1px 1px rgba(0,0,0,.3);
          -webkit-border-radius: 0.5em;
          -moz-border-radius: 0.5em;
          border-radius: 0.5em;
          -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2);
          -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2);
          box-shadow: 0 1px 2px rgba(0,0,0,.2);
        .button:hover {
          text-decoration: none;
        .button:active {
          position: relative;
          top: 1px;

And our buttons will look like:

2 Extract the important stuff into variables.

That’s a lot of CSS but let’s focus on what actually matters: font color, border radius, border color, padding, and background gradients.

Let’s move these values into variables. It’s a good convention to place them at the top of your stylesheet like so:

        /* basic button variables */
        @background_color: #f78d1d;
        @hover_background_color: #f47c20;
        @border_radius: 0.5em;
        @font_size: 14px;
        @font_color: #fef4e9;
        @button_padding: 0.55em 2em;
        @border_color: #da7c0c;

        /* background color gradients for each state */
        @normal_background_top: #faa51a;
        @normal_background_bottom: #f47a20; 

        @hover_background_top: #f88e11;
        @hover_background_bottom: #f06015; 

        @active_background_top: #f47a20;
        @active_background_bottom: #faa51a;

        /* ...previous css with original values substituted for variables... */

Now, already that’s a nice improvement. We can easily make changes to our button styles without having to wade through all that CSS. Want rounder corners? Just increase @border_radius.

3 Make a good thing better with high school math.

While we’ve made an improvement, that still feels like too many configuration options for a simple button. Wouldn’t it be nice, for example, if we didn’t have to worry with all those color variations (i.e. border color, background colors, gradients, etc). It would be much better if we could consolidate all those values into a single variable (e.g. @button_color).

Let’s do just that. First, let’s change @background_color to @button_color. We’ll hold this value constant and set all of our other color-related values relative to @button_color. This means we’ll be able to alter one variable — @button_color — and changes will automatically cascade through related variables.

In case you’re confused, I’ll break it down a bit so you can see what’s going on. We’re just doing some simple math with hexcodes:

        /* we've already set these variables */
        @background_color: #f78d1d;
        @border_color: #da7c0c;

        /* if we know that: */
            @button_color - @border_color = #1D1111
        /* then high school algebra says: */
            @border_color = @button_color - #1D1111

So we can use this concept to set all our color values relative @button_color. Now our configuration options are looking much leaner:

        /* button configuration options */
        @button_color: #f78d1d;
        @border_radius: 0.5em;
        @font_size: 14px;
        @font_color: #fef4e9;
        @button_padding: 0.55em 2em;

        /* color variables set relative to @button_color.
        You probably don't need to change these. */
        @hover_background_color: @button_color - #031100;
        @border_color: @button_color - #1D1111;

        @normal_background_top: @button_color + #031800;
        @normal_background_bottom: @normal_background_top - #062B00; 

        @hover_background_top: @button_color + #010100;
        @hover_background_bottom: @hover_background_top - #082E08; 

        @active_background_top: @normal_background_bottom;
        @active_background_bottom: @normal_background_top;   

        /* ...previous css with original values substituted for variables... */

So now we only need to concern ourselves with five clearly named variables. And we can easily change our style to suit different themes. Change the value of @button_color to #ffb515 and you get yellow buttons complete with CCS3 gradients:

Or change @button_color to #2daebf and @font_size to 22px:

You get the idea. Changing styles couldn’t be easier.

But this is about more than just buttons.

This is just a trivial example of how LESS can make our stylesheets more dynamic. Imagine, for example, WordPress themes where non-developers could alter the entire color scheme by changing a single variable. Or tweak the layout through something like @sidebar_width.

When done well, layouts could even feel a bit like jQuery plugins. Just download the files, change a few configuration options, and you’re ready to roll. This would be especially useful for stylesheets that aren’t too application specific — like wireframe layouts or admin/cms interfaces.

Maybe designers will even start open-sourcing layouts the way developers share plugins? Maybe.

Download the project from GitHub

Tags: ,


Your thoughts?