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: , 6 Comments


jQuery swap form value plugin.

Here’s a simple, lightweight plugin to swap default values in a form field. It works with both textarea and input elements, and runs solidly across browsers. For example:

How to make it work.

Just add a swap_value attribute to your element specifying the value you’d like shown in the field:

       <input type="text" name="username" swap_value="username" />
    

And call the plugin like this:

        $("input[swap_value], textarea[swap_value]").swap_value();
    

You can also change the default text colors by passing arguments to the function:

        $("input[swap_value], textarea[swap_value]").swap_value({
			normal_color: '#3E474D',
			default_color: '#BCBCBD'
        });
    

Don’t forget about accessibility.

For accessibility reasons, you should always include labels for each of your form elements. If you don’t want labels cluttering up your view, I suggest you hide them:

        
        
    

Some more powerful alternatives.

There are some similar, although much more powerful, plugins available for swapping form values. If you’re looking something more fully-featured, I suggest you checkout jquery watermark. Also the in-field labels plugin seems pretty awesome.

Of course, the right choice depends on the needs of your application. Better to go with something simple, if that’s all you need.

Download the project from GitHub

No Comments


How to shorten urls with bit.ly in Ruby on Rails.

First, let’s make a simple retweet link for our application. To keep our views a little cleaner, we’ll make a helper method in app/helpers/application_helper.rb:

        def twitter_url(resource, tweet_text="Check out this article from my-site.com:")
          tweet_url = root_url.chop + url_for(resource)
          "http://twitter.com/home?status=#{tweet_text} #{tweet_url}"
        end
    

This method just builds a url to twitter and supplies some default text which you may optionally override by passing a second argument. Call it in your view like this:

        <%= link_to "Retweet this post!", twitter_url(@post) %>
    

Now, this method works but it would be much better if we could use shortened urls. So let’s change things a bit in order to use bit.ly — twitter’s preferred url shortening service. Before we write any code…

  1. You’ll need to sign up for bit.ly.
  2. And grap your api key.

With that info on hand, we’re ready to interface with the bit.ly api. Let’s make another helper method also located in app/helpers/application_helper.rb:

        def shorten_with_bitly(url)
          # build url to bitly api
          user = "insert-your-username"
          apikey = "insert-your-api-key"
          version = "2.0.1"
          bitly_url = "http://api.bit.ly/shorten?version=#{version}&longUrl=#{url}&login=#{user}&apiKey=#{apikey}"

          # parse result and return shortened url
          buffer = open(bitly_url, "UserAgent" => "Ruby-ExpandLink").read
          result = JSON.parse(buffer)
          short_url = result['results'][url]['shortUrl']
        end
    

This method uses your credentials to build a url to interface with the bit.ly api. Bitly receives our request and returns a JSON object containing a shortened url. We’ll parse this object, grab the shortened url, and return it.

Finally, we need to change our initial twitter_url method to include url shortening:

        def twitter_url(resource, tweet_text="Check out this article from my-site.com:")
          tweet_url = root_url.chop + url_for(resource)
          tweet_url = shorten_with_bitly(tweet_url) if Rails.env.production?

          "http://twitter.com/home?status=#{tweet_text} #{tweet_url}"
        end
    

This is identical to our original method except we’ve added a new line which calls shorten_with_bitly. This line overwrites the tweet_url variable — replacing the long url with a shortened version. Finally, we’ll include a condition to ensure this only happens in production. This saves us from creating a bunch of useless bit.ly links that point to localhost urls.

Some final points.

  • The shorten_with_bitly method borrows heavily form a ruby snippet posted by Puneet Pandey. Pandey definitely deserves some credit here.
  • If you’re looking for a more robust way to interface with the bit.ly api, checkout this url shortening gem by Nasir Jamal. I’ve never used it but appears to be fully featured and well documented.

Tags: , , 2 Comments


« Older Entries | Newer Entries »