Update: Styling the Button Element with CSS Sliding Doors - now with Image Sprites and IE 8 Support

We dusted off our original sliding doors button to give it a much needed update. The button now works with image sprites thanks to the CSS contributions of Louis Walch, and also works with a single block of CSS (we’ve removed the now unnecessary conditional comments for IE) in all major browsers including IE versions 6 through 8.

For those not familiar, form buttons are notoriously difficult to customize because they render differently across browsers and platforms. A few methods for styling buttons are commonly used to make them appear dimensional, uniform, and consistent across browsers, however each has limitations:

  • Apply a single, unique background image with the text “baked in” for each type of button (i.e., “Submit”, “Send message”) and its rollover state. This approach is consistent across browsers but doesn’t scale; you have to create an image for every button in your site, which may not be reasonable to maintain or update. Also, image text is not accessible so a redundant text equivalent must be included in all button markup.
  • Tile a background image on the button element. This works really well when you only need rectangular buttons or have the option to use the CSS3 “border-radius” property to apply rounded corners, as demonstrated in our article on styling buttons with the jQuery UI CSS framework. However, it falls short if your design calls for a custom shape, like a polygon, or if rounded corners must be applied consistently across all browsers, in which case you’d need to create a workaround in JavaScript for browsers that don’t yet support the border-radius property, like IE.
  • Use only background colors, borders and icons as demonstrated by Kevin Hale at Particle Tree. This method requires only basic CSS and minimal extra markup, however the style options are very limited and may not reflect the richness of your design.

While these methods may work in particular situations, we needed a more flexible solution that accommodated a wider range of styles.

Our solution

We’re often designing and developing complex applications with buttons that are styled with background images, background colors, icons, and sometimes a combination of all three. Ideally, our buttons would:

  • use the sliding doors method introduced on A List Apart so that we can employ dimensional background images in various shapes and allow the background to scale with the text size to some degree,
  • use sprite images, where multiple button states are combined into a single image file and repositioned on hover, to limit the number of image downloads,
  • allow us to use HTML text for the button labels so that we could reuse the same button style many times without having to cut unique images for each, and
  • not require JavaScript for form submission or rollovers to ensure that the buttons are usable without JavaScript enabled.

The result is a cross-browser method for styling button elements with sliding door sprites.

Examples

The buttons shown use the same markup and style — only the label text is different.

Demo Page

Sprite image

The background sprite contains four images: each button has a left and right “door,” and each door has two states, default and hover. Update 4/27/09: Our example button now references a single sprite image for both doors and their hover states as shown (thanks to Louis Walch for the update!):

Buttonsprite

We recommend adding at least 20px vertical space between the stacked states to prevent one state from appearing when it should be hidden. (We could add “overflow: hidden” to the button rule instead, but doing so would mean that we’d have to reinstate conditional styles for IE, which requires that the overflow property be visible — otherwise you may see extra right and left padding in IE. We figure this is a reasonable workaround to avoid having to maintain separate style blocks.)

Markup

Button markup consists of a button tag around a span tag, and label text is written into the span. Both tags are necessary to support the sliding door background images: the button tag’s background image is shorter with right corners, and the span’s background image is larger with left corners. We found in our tests that the right image should be at least as wide as it is tall to avoid gaps between the doors.

And last but not least, we assigned a class to the button element to apply our design; in this case, “submitBtn.” Styles for the span tag are assigned with descendant selectors.

<button value="submit" class="submitBtn"><span>Submit</span></button>

CSS

/* REQUIRED BUTTON STYLES: */
button {
    position: relative;
    border: 0;
    padding: 0;
    cursor: pointer;
    overflow: visible; /* removes extra side padding in IE */
}

button::-moz-focus-inner {
    border: none;  /* overrides extra padding in Firefox */
}

button span {
    position: relative;
    display: block;
    white-space: nowrap;
}

@media screen and (-webkit-min-device-pixel-ratio:0) {
    /* Safari and Google Chrome only - fix margins */
    button span {
        margin-top: -1px;
    }
}


/* OPTIONAL BUTTON STYLES for applying custom look and feel: */
button.submitBtn {
    padding: 0 15px 0 0;
    margin-right:5px;
    font-size:2em;
    text-align: center;
    background: transparent url(images/btn_blue_sprite.gif) no-repeat right -140px;
}

button.submitBtn span {
    padding: 13px 0 0 15px;
    height:37px;
    background: transparent url(images/btn_blue_sprite.gif) no-repeat left top;
    color:#fff;
}

button.submitBtn:hover, button.submitBtnHover { /* the redundant class is used to apply the hover state with a script */
    background-position: right -210px;
}

button.submitBtn:hover span, button.submitBtnHover span {
    background-position: 0 -70px;
}

Supported Browsers

So far it works in:

  • IE 6+
  • Firefox 1.5+
  • Opera 8+
  • Safari 3+
  • Chrome 1.0

Update 4/27/09: The button styles now work in Chrome — thanks again, Louis!

Caveats

IE 6 does not support the “:hover” pseudoclass on elements other than anchor tags. To get the hover to work in IE6, create a class that duplicates the :hover styles, and then script a function to toggle that class on/off like the one below written with jQuery:

<script type="text/javascript">
$(function(){
    $('.submitBtn').hover(
        // mouseover
        function(){ $(this).addClass('submitBtnHover'); },

        // mouseout
        function(){ $(this).removeClass('submitBtnHover'); }
    );
});
</script>

Credits

Our original button styling technique was motivated by the Particle Tree article, Rediscovering The Button Element by Kevin Hale. Louis Walch provided updated CSS to support sprites and also helped us debug the final examples shown here.

All blog posts