Ga direct naar


Transforming the button element with sliding doors and image sprites

Friday 13 March 2009 11:06

One of the elements lacking a standardized look is the button element. In this article, we're going to transform the buttons image from fixed to flexible and good looking using HTML and CSS. Let's get styling!

By Peter Slagter

Introduction

In the past years, webdesign and webdevelopment have become mature. The user is the center of development, and deserves an user interface which supports and leads users to accomplish the goal of the website. Building consistent, attractive and cross-browser compatible user interfaces can be a tough job. This especially becomes apparent when you're busy giving your forms the desired look and feel. One of the form-elements lacking a standardized look is the button element. Let's go tame that button, so it fits into any design.

Introducing the button element

First, let's get to know the button element. The HTML 4.01 specification provides the following information about the button element:

Buttons created with the BUTTON element function just like buttons created with the INPUT element, but they offer richer rendering possibilities: the BUTTON element may have content. For example, a BUTTON element that contains an image functions like and may resemble an INPUT element whose type is set to "image", but the BUTTON element type allows content.

Visual user agents may render BUTTON buttons with relief and an up/down motion when clicked, while they may render INPUT buttons as "flat" images.

That sounds great. Even though the W3C recommendations states two advantages of using the button element, it seems that many developers forgot about it, or aren't even aware of its existence.

With that in mind, let's find out the possibilities of the button element. User Interfaces are often heavily dependent on background images, icons and other fancy layout-elements. We want our buttons to blend into that perfectly as well, and accomplish the following:

Our goal

Before we get into technical information and details, let's take a look at what we are going to build. I've created three buttons, two with basic terms, and another one with some more text. The buttons look great, have round corners, a hover state and a focus state. Feel free to move your mouse over the buttons, or even click them ;) (Chrome users will see a minor bug, we'll come to that later):

The markup and images

Let's have a closer look at one of the buttons markup. We'll inspect the following button:

As you can see, the markup is really basic. For flexibility reasons, we wrapped the inner text into a span element. This makes it possible for us to use the sliding doors technique, which enables us to blend the button into any user interface. Without the span element inside the button, we wouldn't be able to create a button with round edges and a flexible width.

To give the button it's look, I used an image sprite containing the three states our button has (the hover and focus state are the same):

Background sprite of a button

The CSS

Now, its time to style our buttons. Let's start with the button element:

	button {
   float: left;
   padding: 0 15px 0 0;
   height: 25px;
   border: 0;
   cursor: pointer;
   text-align: center;
   color: #f9f9f9;
   background: transparent url(images/button-sprite.png) no-repeat right top;
   font: bold 14px "Myriad Pro", arial, sans-serif;
   overflow: visible;
}

Some of the properties and values (padding, background and font) are written with shorthand properties and values. I want to address three values and explain why they'r used:

  1. float: left;
    I wanted to point out that you should, logically, only apply this value if you want your button to float. In my example, I got three buttons floating next to eachother, hence the value is present.
  2. padding: 0 20px 0 0;
    The padding-right is used to show the top-right image in our sprite. If you remove the padding, the span element will overlap the button completely, hiding the right edge of the button.
  3. overflow: visible;
    For some reason Internet Explorer decides to stack padding depending on the width of the content inside the element. This value eliminates the stacking. More information here and here.

Secondly, the span element inside our button needs some CSS to get the job done.

button span {
   display: block;
   padding: 0 0 0 15px;
   height: 25px;
   line-height: 25px;
   white-space: nowrap;
   background: transparent url(images/button-sprite.png) no-repeat left -25px;
}

Again, i'd like to address three values in our CSS rule. Even though it may sound really basic, questioning why certain values are present, is a good habit.

  1. display: block;
    By default, a span element is an inline element. We need to be able to add box properties like height and padding to our element, so we need to change its display setting to block.
  2. line-height: 23px;
    To vertically align our text in the middle of our button element, we'll have to set the line-height to a value within the 20-25px range. I chose 23px.
  3. white-space: nowrap
    This settings makes sure that all of the words you want to show on your button are visible in Internet Explorer. If you forget this setting, you'll notice that 'This is my sentence' will display as 'This'.

Thirdly we'll add the CSS necessary to add effects on the hover- and focusevents. Please note that Internet Explorer 7 lacks the implementation of the :focus pseudoclass and Internet Explorer 6 and lower lack the :hover pseudoclass as well. Both can be simulated / fixed using javascript. For example, Dean Edwards javascript library fixes the most common IE6 and IE7 problems.

button:hover,
button:focus {
   background-position: right -56px;
}

button:hover span,
button:focus span {
   background-position: left -84px;
}

button:focus {
   margin-top: 1px;
}

We've come to the point that we're ready to view the buttons in a couple of browsers. Let's see:

Image showing the look of a button in different browsers

You'll notice that there's still a little bug in Firefox and Google Chrome. The differences in browser implementations become really apparent now. Let's find out whats happening, and additionally how to fix the problem.

If you inspect our CSS closely, you'll notice that there isn't a conflicting value that causes the extra padding in our button. So where does it come from? Every browser has implemented User Agent stylesheets. If a browser gets a HTML document served without styling information attached to it, it will still show some basic formatting: the User Agent stylesheets. Jens Meiert has written a good article on User Agent stylesheets, there's even a list with CSS files you can download.

If you open Firefox' forms.css, you'll see the following code:

button::-moz-focus-inner,
input[type="reset"]::-moz-focus-inner,
input[type="button"]::-moz-focus-inner,
input[type="submit"]::-moz-focus-inner,
input[type="file"] > input[type="button"]::-moz-focus-inner {
   padding: 0px 2px 0px 2px;
   border: 1px dotted transparent;
}

Mozilla supports a number of extensions to CSS that are prefixed with '-moz'. These include a number of capabilities, including rounded borders, and the ability to specify different box width and height calculations to more easily support browers that perform such calculations in a non-standard way. An overview of all available settings can be found here.
So apparently the Mozilla extensions are conflicting with our CSS. The first selector is the one we need to fix:

button::-moz-focus-inner /* fixing evil default firefox padding */ {
   padding:0;
   border:none;
}

There we go, the button we created will show correctly in Firefox as well. So what happens in Google Chrome?

Google's goal with Chrome form implementation, is to behave exactly the same as Firefox. Obviously and unfortunately, they introduced the same bug, which in Chrome can't be fixed. I'm still searching for a way to get around it, but I'm sure Google will fix it sooner or later. The bug has been reported to the Google Headquarters.

Summary

We've looked at the button element and discovered it's possibilities and limits. We've seen that its possible to create flexible and good looking button elements, with cross-browser support.

Pros

  • Semantic HTML;
  • Fast :hover changes;
  • Less HTTP requests;
  • Good looking, flexible buttons.

Cons

  • Needs a 'hack' to disable the native User Agent CSS in Firefox.
  • Google Chromes similar bug can't be fixed at the moment (I dont worry too much about Google Chrome yet, though).

The method described in this article, covers the usage of image sprites. It's possible to get this working in Chrome aswell, but you will have to make separated images instead of using a sprite. If there's demand for an article which explains how to get this done, I'll write a follow up.

The code

button {
   float: left;
   padding: 0 15px 0 0;
   height: 25px;
   border: 0;
   cursor: pointer;
   text-align: center;
   color: #f9f9f9;
   background: transparent url(images/button-sprite.png) no-repeat right top;
   font: bold 14px "Myriad Pro", arial, sans-serif;
   overflow: visible;
}

button span {
   display: block;
   padding: 0 0 0 15px;
   height: 25px;
   line-height: 25px;
   white-space: nowrap;
   background: transparent url(images/button-sprite.png) no-repeat left -25px;
}

button:hover,
button:focus {
   background-position: right -56px;
}

button:hover span,
button:focus span {
   background-position: left -84px;
}

button:focus {
   margin-top: 1px;
}

button::-moz-focus-inner /* fixing evil default firefox padding */ {
   padding:0;
   border:none;
}

If you feel something is missed out here, or needs further explanation, feel free to post your comment!

«Back

Reactions on "Transforming the button element with sliding doors and image sprites"

garfix
Placed on: 03-13-2009 14:20
Patrick van Bergen
User icon
to be continuum
Well done, Peter! The explanation is thorough and the details have been worked out really well. The implementation of the "focus" state is surprising Smile
luc longley
Placed on: 03-13-2009 15:37
Yes, this is a well done explanation.
Edited
Pjottr has edited this message on: 03-16-2009 10:56
Bronson
Placed on: 03-14-2009 17:54
Awesome post and the end result is very cool indeed. Thanx.
Narhir
Placed on: 03-16-2009 10:52
Nice one Smile very interesting post Biggrin I will have to try it and do step by step Smile I didnt know that I can do so much with button Smile

Keep it up Smile it is good work man : )
Cal Wilson
Placed on: 03-17-2009 11:04
Wow Peter, great technique. And a really easy-to-understand write up as well. One for the bookmarks!
MooCow
Placed on: 05-03-2009 17:14
I only skim the article rapidly, but couldn't we force/emulate the Firefox/Chrome setting on the other browsers instead?
parkben
Placed on: 05-06-2009 18:18
Hi Peter, this is great. We need more of these well-written articles on the web!

One question - I'm testing this page in IE8 and the button displays correctly, but on the mousedown it breaks (looks like the FF and Chrome images you have above). Is that my browser, or would you know of a fix for that?
craig
Placed on: 06-07-2009 14:53
seriouly, chrome is a promising browser, in a few years from now no on would know how it dominating, how could you ignore it ?
Shahriat Hossain
Placed on: 07-06-2009 15:46
After 5 yrs walk of my web application programming I have decided to walk with this front end markup because of fast revolution of markup and inspiration from such post. Thanks for sharing your knowledge.
Nikita Sumeiko
Placed on: 07-08-2009 18:31
Well done!
I think it's a great way, if we work with <button> tag.
But usually we use input tag in the form elements. I have spent a lot of hours surfing the Internet, and made a really clear working cross-browser sliding door input button.

I wish to show how:
http://www.manakor.org/x...ding-door-input-button/

So, we have got two methods for now. Thanks.
JC
Placed on: 12-01-2009 22:56
Like parkben mentioned, the mousedown in IE will push the image left image down. Creating an image break.

Is there a solution for this button behavior in IE?
Hap
Placed on: 12-14-2009 19:04
Found that IE8 tries to simulation a button 'press' automagically for you. Leave it to Microsoft to implement 'Microsoft extensions to the CSS standard' instead of just following the standard. See this post:

http://labs.findsubstanc...-image-on-click-css-bug

Depending on the way you have constructed your button and span markup, the solution involves using the IE8 extensions '-ms-background-position-x' and '-ms-background-position-y'. I added the following to my CSS to overcome the bug:

.custom_button:active
{
-ms-background-position-x: right;
-ms-background-position-y: -54px;
}

Stan
Placed on: 03-04-2010 13:17
I like the Safara typo Smile
Andrew
Placed on: 07-25-2010 04:51
I love detailed tutorials like this one! Fantastic stuff! Thanks so much for sharing with new designers like myself.
q455923354
Placed on: 09-01-2010 04:21
Found that IE8 tries to simulation a button 'press' automagically for you. Leave it to Microsoft to implement 'Microsoft extensions to the CSS standard' instead ofhttp://www.edhardy-sale.net/ just following the standard. See this post:
oomes
Placed on: 11-15-2010 16:46
Great! Thanks.

Procurios zoekt PHP webdevelopers. Werk aan het Procurios Webplatform en klantprojecten! Zie http://www.slimmerwerkenbijprocurios.nl/.


Hello!

We are employees at Procurios, a full-service webdevelopment company located in the Netherlands. We are experts at building portals, websites, intranets and extranets, based on an in-house developed framework. You can find out more about Procurios and our products, might you be interested.

This weblog is built and maintained by us. We love to share our ideas, thoughts and interests with you through our weblog. If you want to contact us, please feel free to use the contact form!


Showcase

  • Klantcase: Bestseller
  • Klantcase: de ChristenUnie
  • Klantcase: Evangelische Omroep
  • Klantcase: de Keurslager
  • Klantcase: New York Pizza
  • Klantcase: Verhage

Snelkoppelingen