Styling BUTTONS, and achieving sliding doors with them

Published on Thursday, March 13th, 2008

As you all know, form elements aren’t that easy to style, especially not consistently. At a first glance, the button element seems like a sure winner, but once you delve into it…

Why style buttons?

There just are some designs where it would look better, as well as give the end user a better experience if the buttons match the rest of the web site. I have full respect for native looking buttons overall, but in some scenarios they just don’t cut it.

What’s button?

I won’t really go into that here, so I recommend reading Push my button.

What’s the gain?

Besides from getting a more consistent design and experience, a button can, basically, have any HTML content; meaning, you can have regular text inside of the button element. For example:

<button type="submit">
	<span>Some <strong>text</strong><span>
</button>

This means that you can handle a web site which will be in several languages from code, instead of producing image buttons to no end. It also means that you can use a sliding doors approach to create two images to use with all buttons on the site, no matter their width.

These images will also be cached when they are first encountered, which means that the images for all buttons in the web site will be preloaded.

Implementing it

Well, it’s almost as easy…

One needs to consider that some web browsers (yeah, give it a wild guess) applies secret padding, meaning, padding which you can’t remove nor disable. Then you need to consider the workarounds. I’ve put way too many hours into getting this consistent now, and I thought I’d share the solution with you.

According to the W3C validator, this is valid code, but some other HTML validators might give you a warning (not sure why since it consists of two inline elements). One option can be to use div elements instead of span, but then you need to float them to make it work in IE. While not semantically perfect, this works for me:

After Guilherme’s excellent link suggestion, this code has been completely revised/rewritten, so it is now valid and works in all major web browsers (IE 6+, Firefox, Safari, Opera). The only downside is a small bug in Firefox, where it will gain a couple of extra pixels of padding to the right, but only a trained eye will see that.

HTML

<button type="submit">
	<span>Search</span>
</button>

The span element is there to offer the first image, and wouldn’t work inside of the button because of above-mentioned padding problems.

CSS

/*
	Setting general button styles.
	Background position can't be set to "top",
	because of Firefox behavior.
	overflow: visible; is to remove magic padding in IE.
*/
button {
	text-align: center;
	background: URL(button-end.png) no-repeat right;
	border: 0;
	margin: 0;
	padding: 0 3px 0 0;
	overflow: visible;
}
/*
	Sets the general styles for the span within the button
	content, and the starting image. This image contains the
	rounded corners to the left and is as wide as
	the widest button might become.
*/
button span {
	position: relative;
	display: block;
	white-space: nowrap;
	height: 23px;
	color: #fff;
	font: bold 11px/23px Arial, Helvetica, sans-serif;
	text-transform: uppercase;
	background: URL(button-start.png) no-repeat left top;
	padding: 0 5px 0 8px;
}

Try the demo

Instead of just showing you code, I thought I’d be nice to show the actual code in action as well. Try the Styling BUTTONs demo to see for yourself.

Taking it further

Of course you can then tweak the image and button content to handle possible line breaks, just too large font or whatever. Consider this step 1 in your button conquest.

A word of warning

While this design approach should hold up for you, you need to be aware of a couple of functional bugs present in all available versions of Internet Explorer. Instead of posting its value, the button will actually post its innerHTML when it is submitted.

If there are several button elements in a form it will post the values for all of them, and not just the one that was clicked.

However, if you only have one button in your form, and you don’t need to read the value of the actual button, this is a great approach to spice up your design.

19 comments

  • Guilherme Zühlke O’Connor
    March 13th, 2008 at 18:21

    Personally I like the button element because it detaches a bit the button from a generic <input> element (after all, there is a world of difference between a “hidden”, a “button”, a “text” and many other elements ;)). I like to be able to semantically distinguish them in their nature.

    Further, I like the fact that the button has content, this makes a lot of sense to me. You have a button that does something when clicked, and it can have content of its own… well, almost, since the implementations are not all that flexible and it is hard to style it, but is hard to style <input> elements either, so I like buttons that are <button>.

    Now, it seems there is a solution with the span inside of the button element which is presented by FilamentGroup.com.

  • kimblim
    March 13th, 2008 at 21:06

    I love the button-element, but unfortunately it doesn’t work in all mobile browsers, and that is a big accessability problem.

  • Andy Ford
    March 13th, 2008 at 22:04

    If there are several button elements in a form it will post the values for all of them, and not just the one that was clicked.

    Which value? The value of the innerHTML or the value of the value attribute?

    Is there a safe way to have multiple button elements in a form in IE?

    Either way, it’s a bummer that IE is such a steamy pile.

  • nortypig » Blog Archive » Styling Form Buttons into Sliding Doors
    March 13th, 2008 at 23:52

    [...] Nyman has posted an informative article on styling form buttons into sliding doors and explains why you may want to consider [...]

  • Morgan Roderick
    March 14th, 2008 at 11:01

    Personally, I am not much for styling form elements, but prefer to leave that up to the browser. But, for those situations, where you have to style them, it’s great to have another tool in the toolbox.

    Thanks for sharing Robert :-)

  • Robert Nyman - author
    March 14th, 2008 at 11:22

    Guilherme,

    I do like the button element, as long as I can control it. :-)

    Thanks for the link, it was great inpsiration! I analyzed it, and revised/rewrote my code to have the span element within the button, and ironed out a bug they seemd to have with IE.

    Please try the updated demo.

    kimblim,

    That doesn’t sound good. Do you have any examples in which, and what happens?

    Andy,

    In IE 6, it sends the innerHTML of every button in that form, in IE 7, it sends the innerHTML of the clicked button.

    I think it’s safe to have multiple butons, as long as you don’t expect to read any value from it, or take any specific action on what button was clicked.

    Morgan,

    I agree overall, but sometimes the gain of doing it can’t be overlooked.

  • Guilherme Zühlke O’Connor
    March 14th, 2008 at 16:43

    Robert, that new solution of yours is way cooler, IMO.

    I agree with you that is horrible not being able to control elements, but still I like the semantic meaning of the tag. I wish other input elements could have a tag for themselves like <button> and <textarea>.

    If I was to hate tags based on control I couldn’t support HTML at all until [guess-who] version 6 and previous were dead and buried (and possible further versions as well) :-)

  • Robert Nyman - author
    March 14th, 2008 at 17:08

    Guilherme,

    Thank you! :-)
    And I agree, many elements don’t have specifically semantic names…

    If I was to hate tags based on control I couldn’t support HTML at all until [guess-who] version 6 and previous were dead and buried (and possible further versions as well) :-)

    Ha ha! :-)

  • Wolf
    March 17th, 2008 at 11:32

    But, how do I get rid of the dreaded black border in IE6 and IE7?

  • Robert Nyman - author
    March 17th, 2008 at 13:08

    Wolf,

    By setting border: none; or border: 0; in the CSS code.

  • RUDEWORKS
    March 18th, 2008 at 10:35

    [...] Robert Nyman nos proporciona una buena manera de dar estilo al elemento <button>. El único problema son [...]

  • Andres
    March 18th, 2008 at 14:48

    Hey i thought you guys might like this soup of buttons. I’ve been working on this for a while now, and up to now, no one has reported any new bugs. I think it’s ready for a stable release… Let me know what you think…

    CSSButtons.net

    Thank you!!
    email me at [projects@dpinyc.com]

  • Robert Nyman - author
    March 19th, 2008 at 8:40

    Andres,

    Thanks for the tip!

  • Niklas
    March 19th, 2008 at 10:06

    This is really cool! Do you have any plans on taking the next step with this? And by that I mean to make it work with resizeable text.

  • Robert Nyman - author
    March 19th, 2008 at 10:22

    Niklas,

    Thanks!
    And, no plans. But resizable text will work to a certain extent with this solution, depending on the chosen height and background image size.

    A simple solution to make that better is to have a footer element within the button which will in turn have an image which is the entire footer image.

  • Jens Wedin
    March 27th, 2008 at 8:46

    I´ve made a quick demo with flexible buttons after reading this post. You can check it out at:
    http://jedisthlm.com/2008/03/27/flexible-CSS-buttons/

  • Robert Nyman - author
    March 27th, 2008 at 9:49

    Jens,

    That’s great! Thanks!

  • Biran
    August 27th, 2008 at 15:02

    I wrote a button adapter for ASP.NET that converts the asp:button control to use the button element. Now you can have functionality and sexy…

    http://www.delphicsage.com/home/blog.aspx?d=239&title=Convert_Your_ASP:Button_Controls_to_Sliding_Doors_Styled_Button_Elements

  • Robert Nyman - author
    August 27th, 2008 at 21:00

    Biran,

    Cool, thanks for sharing!

Share your thoughts:

HTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> . If you want to display code examples, please remember to write &lt; for < and &gt; for >.

Comment preview

Top results