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

Posted by Maggie on 04/24/2009

Topics:

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!):

Button sprite

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.

Book cover: Designing with Progressive Enhancement

Enjoy our blog? You'll love our book.

For info and ordering: Visit the book site

Comments

Excellent work, guys. We’re currently in the middle of a redesign at work and I’m dying to get away from the ‘baked in’ image buttons. I think I’ll present this article at our next designers meeting. :)

Comment by Mike T. on 04/27  at  06:04 PM

the “right corner” images are off by 1 pixel up in Chrome 2.0.174.0

other than that, very nice work

Comment by Luka Kladaric on 04/27  at  06:13 PM

@ Luka Kladaric:  we tried to come up with a workaround for Chrome, but no luck.  It seems to be an issue with the way Chrome renders the button element because removing padding/margin/borders/you-name-it had no effect.  If you—or anyone else out there—know of a fix that won’t break the styling in Safari, please share!

Comment by Maggie (Filament) on 04/27  at  06:20 PM

@Mike T:  thanks!  Glad we could be of help. :)

Comment by Maggie (Filament) on 04/27  at  06:21 PM

Nice to see this done with a button element. Why did you decide to not incorporate both the long and short images into one sprite?

Comment by Ryan on 04/27  at  06:28 PM

@Ryan, it’s actually my fault that it was not built into one sprite. Not sure why I couldn’t get it to work when I originally did this, but here are the changes needed to make this into a single sprite:

@Luka & Maggie : I actually may have discovered a workaround for the Chrome problem as well. Css updated below. Tested in IE6, IE7, Safari 3, FF and Chrome.

New Sprite:
http://louiswalch.com/beta/btn_blue_sprite.gif

CSS:
http://pastie.org/460158

@Maggie: Feel free to delete this comment after you roll this in. Sorry for not realizing this before you went to press.

Comment by Louis W on 04/27  at  10:09 PM

@Louis W:  Nice work!  We’ve incorporated it into the examples in this post.  Thanks again!  :)

Comment by Maggie (Filament) on 04/27  at  11:19 PM

confirm working in Chrome 2.0.174.0 :) good job, guys!

Comment by Luka Kladaric on 04/28  at  12:35 AM

For the future it would be easier to create a <div> </div> tag in order to present a sample of the CSS embedded directly on the website herein. This is needed for example in my case because it’s kinda tricky to load each CSS and test it on my rent a car site. Otherwise, just wanted to say that your scripts are great!

Comment by Masini Inchirieri Bucuresti on 05/01  at  06:56 PM

Could someone explain:
@media screen and (-webkit-min-device-pixel-ratio:0) {
/* Safari and Google Chrome only - fix margins */
button span {
margin-top: -1px;
}
}
Dreamweaver is highlighting this as code error not seen this befor
Thanks Mike

Comment by Mike Gadd on 05/06  at  09:31 AM

@mike:
The CSS you included is a css hack which will make the enclosed styles only apply to Chrome and Safari. It is needed in order to fix a problem with how margins are applied to the button in Google Chrome.

It is ok if Dreamweaver is highlighting this as invalid - in a way it is. But leave it in there if you would like your buttons to appear correctly across all browsers

If your interested in more browser specific css hacks check out this page:
http://ajaxian.com/archives/css-browser-hacks

Comment by Louis W on 05/06  at  03:25 PM

Feel free to add Safari 2 (2.0.4 aka 419.3) on your supported browsers list.

Comment by Michał on 05/12  at  05:32 PM

In IE8 when the button is click, there’s a pixel missing from the bottom (and top) on the right side of the button.  Is there a way to fix this?

Comment by Jane on 05/21  at  03:56 AM

I think the efficiency of the CSS paired with clean visual design here are great. I’m a fan of Filament, as well as Bowman’s ‘Sliding Doors’ and Cederholm’s ‘Bullet-Proof’ philosophies/techniques.

What I’m most interested in is IF you do employ this CSS/<button> tag technique in your site design and architecture:

How is everyone getting around the issues that IE incorrectly submits the inner HTML of the <button> or returns all values to all buttons when multiple buttons exist on a page?

I’m a visual web designer for a team of developers that would come along with me on this technique--except for the IE issue, which may simplify the HTML/CSS but complicates the form submission to a painful level.

Thanks,
Chris

Examples:
http://www.experts-exchange.com/Software/Internet_Email/Web_Browsers/Q_21599546.html

http://www.w3schools.com/tags/tag_button.asp

http://msdn.microsoft.com/en-us/library/ms535211(VS.85).aspx
“New for Internet Explorer 8 Internet Explorer 8 and later. When the BUTTON element is submitted in a form, the value depends on the current document compatibility mode. In IE8 mode, the value attribute is submitted. In other document modes and earlier versions of Internet Explorer, the innerText value is submitted.”

Comment by Sabatino on 05/26  at  06:47 AM

Doesn’t seem to be working for me in IE7 compatibility mode (IE8) on http://bookhookup.net/sell. To replicate, enter any bogus value and try clicking “Get Started"… it won’t submit.

CSS is unchanged from the example (except for custom padding values)
Markup is as follows (minus spaces of course ;) ): < button value="submit" class="formbutton">< span>Get Started</ span></ button >

Comment by Joe on 06/07  at  01:20 AM

@Joe
Your are missing a type on your button. If you want it to submit you need type="submit"

Types can be any of:
button <- default
submit <- will submit the current form the button is in
reset <- will reset the current form the button is in

Comment by dotnetCarpenter on 06/11  at  10:01 PM

@dotnetCarpenter D’oh! Thanks so much, dunno why I missed that.

Comment by Joe on 06/12  at  02:50 AM

Could you post an example of this problem? I use multiple buttons using this method throughout my web apps without issue.

Comment by LouisW on 06/13  at  05:25 PM

@LouisW: Hi, since you’re using multiple buttons thoughout your web app, I’d ask you too if you have any advice or insight that you use to support IE, even back to IE6 on this issue: [see earlier post]

“How is everyone getting around the issues that IE incorrectly submits the inner HTML of the <button> or returns all values to all buttons when multiple buttons exist on a page? “
http://msdn.microsoft.com/en-us/library/ms535211(VS.85).aspx
[copy/paste this to view--parens don’t survive in the comments]

Thanks,
Chris

Comment by sabatino on 06/13  at  05:57 PM

@Jane The best option I’ve found to fix the 1px background shift in IE8 is using Microsoft’s CSS vendor extensions (which work in IE8 but not previous versions). I’ve documented the solution here: http://bit.ly/NSd0b.

Comment by Cory Duncan on 06/20  at  09:41 PM

Hello guys, great example, but I have some trouble with Opera 9.24. The <button> background goes down on about 2px. If you have any sollution, please sent the link on it. Thx.

Comment by Roman on 07/03  at  12:21 AM

Thanks for this great article.
While playing with the demo i’ve noticed 2 things:
In Firefox 3.5 there’s an extra gap inside the button, to remove id add padding:0 (it’s Mozilla’s forms.css issue) :

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

Second issue: under the button there’s about 5 pixel space in IE. (It’s easy to notice, when you have image without transparent gaps between the sprites). To get rid of it just add overall height to button.submitBtn:

button.submitBtn {
height:50px; (37px height + 13px top padding)
padding: 0 15px 0 0;
...
}

Comment by nmstudio on 07/06  at  11:25 PM

Man nmstudio, good find on the focus inner problem. That was driving me nuts and wouldn’t show up ANYWHERE in firebug.

Comment by Bob Spryn on 07/18  at  11:24 PM

So here’s an odd problem.

With firefox 3.5 and Firebug 1.4 things look fine… until you open the firebug panel.

It looks like for some reason as soon as you open firebug, firefox now understands this rule:

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

Try it out! Weird eh?

Comment by Bob Spryn on 07/18  at  11:55 PM

Here’s my new button. It donesn’t need extra markup like spans or b tags and yet it’s transparent without opaque corners or background to hide the other half. It submits hitting enter, because it IS the actual submit button, not a link with JS submit function.

I named it “the levitating submit button”, since in hangs completely out of the label tag.
http://seosumo.com/simplest-transparent-css-submit-button-ever

Comment by sergio zambrano on 07/23  at  11:56 PM

Great stuff… I did notice in chrome a one pixel shift when you’re not viewing 100%, but zoomed in or out.

Comment by Michael Torfs on 08/01  at  11:21 PM

Hi all

first of all nice job and keep it up on the fantastic improvements!

i only have one minor prob, im getting an irritating 2px margin on the left hand side of the button only in IE but ff and safari are perfect, any idea why this is happening?

http://skitch.com/marioborg/b4mqn/ieprob

Regards
Mario

Comment by Mario Borg on 08/06  at  11:05 AM

Hi there,

just a quick update. this is my css based on yours which i found just seems to tidy things up (odd padding differences etc). Iv tested on chrome ie8 and firefox but cannot test in safari or earlier ie’s as don’t have access. don’t know if its valid etc but it seems to make the buttons look very very similar across the 3 browsers iv tested:

button.submit-btn {
position: relative;
border: 0;
padding: 0 3px 0 0;
margin: 0;
cursor: pointer;
overflow: visible; /* removes extra side padding in IE */
font: 12px Arial, Helvetica, sans-serif;
font-weight: bold;
text-align: center;
background: transparent url(’../images/button.gif’) no-repeat right -62px;
}

button.submit-btn span {
position: relative;
display: block;
white-space: nowrap;
line-height: 21px;
padding: 0 8px 0 10px;
height: 21px;
background: transparent url(’../images/button.gif’) no-repeat left top;
color: #2F6681;
}

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

button.submit-btn:hover span, button.submit-btn-hover span {
background-position: 0 -31px;
}

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

button.submit-btn::-moz-focus-inner {
margin-right: -3px; /* overrides extra padding in Firefox */
}

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

my button state images are 21px high with 10px in between each state

thanks for the good work

ben

Comment by Ben Grice on 08/13  at  05:09 PM

Could you post an example of this problem? I use multiple buttons using this method throughout my web apps without issue

Comment by توبيكات on 08/16  at  02:15 AM

this post made my day(weel, night actually, its 11PM here). thnx a lot :)

Comment by Razvan Pavel on 08/18  at  09:57 PM

توبيكات , no problem, like i said my changes just seemed to tidy up some little pixel differences here and there. may just be me tho so i wouldn’t take it as right. Just thought id add the comment on the off chance that someone was having slight differences so they could try what worked for me.

Cheers
Ben

Comment by Ben Grice on 08/19  at  11:17 AM

I am curious to find out if anyone has found a way to incorporate a pressed button state into this CSS?

I would like to add the ability to have the button simulate a pressed state upon the click when submitting the form.

Also, has anyone come up with a proper fix for the bug in IE8 involving the 1 pixel shift when you click on the button. I read the following article

http://bit.ly/NSd0b

but I wasn’t sure if there had been further solutions identified.

Any help would be greatly appreciated. This is an excellent method for adding nice touches to boring form buttons!!!! Thanks to folks like you who make designing new and fulfilling everyday!

Comment by Tim Wilson on 08/25  at  11:33 PM

For a pressed button state just add a :active class (identical to how :hover is.

Your bit.ly url is 404ing.

Comment by Louis W on 08/25  at  11:46 PM

Thanks for the info on the active class, I will run with that....

I checked the other URL and it seems to work fine for me:

http://bit.ly/NSd0b

I am seeing a 1 pixel shift on the right side of the button in IE8 and all looks well in Chrome.

The URL referenced above mentions a few suggested fixes, but all of them have their downsides. i am curious to know if everyone that uses this is seeing the same issue in IE8?

Any insight would be greatly appreciated!

Comment by Tim Wilson on 08/26  at  06:06 AM

Tim, did you ready my comment “Ben Grice on 08/13 at 10:09 AM”? i made a few changes that seemed to work for me, that why i posted them. try what i changed and see if that helps?

Cheers Ben

Comment by Ben Grice on 08/26  at  12:05 PM

Ben,

Thanks for the response, however I performed a diff on your posted code and my code and tried using your version and I actually ended up with the same 1px shift in IE8 and ended up causing another alignment issue with Chrome.

Therefore, I reverted back to the code I was using previously as it seems to work in all required browsers. Now the only issue I need to solve is still the IE8 1px shift issue.

Can someone take a look at my code below to see if there may be a solution for this issue as I would love to use this as a solution for an ongoing project, but cannot until I have some plausible fix for the IE8 pixel issue:

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.submit-btn {
position: relative;
border: 0;
padding: 0 15px 0 0;
margin-right: 5px;
font-size:2em;
text-align: center;
overflow: visible; /* removes extra side padding in IE */
font-weight: bold;
text-align: center;
background: transparent url(btn_blue_sprite.gif) no-repeat right -140px;
}
button.submit-btn span {
position: relative;
display: block;
white-space: nowrap;
padding: 7px 0 0 15px;
height: 44px;
background: transparent url(btn_blue_sprite.gif) no-repeat left top;
color: #FFFFFF;
}
button.submit-btn:hover, button.submit-btn-hover { /* the redundant class is used to apply the hover state with a script */
background-position: right -210px;
}

button.submit-btn:hover span, button.submit-btn-hover span {
background-position: 0 -70px;
}

Comment by Tim Wilson on 08/26  at  07:26 PM

I ran into a problem that seemed to affect only Google Chrome (and not Safari 4).

There was a gap appearing between the button bg image and the span bg image. Turns out the right part of the image in the sprite needs to be at least ~15px wide (with matching right/left padding).

Not sure the exact width, but I was getting the problem when I had button { padding: 0 10px 0 0; } and button span { padding: 0 0 0 10px; }

Hope that helps if someone else comes across the same issue.
Everything worked beautifully as soon as I increased the image width and bumped up the padding to button { padding: 0 15px 0 0; } and button span { padding: 0 0 0 15px; }

Comment by Karl Swedberg on 09/01  at  07:15 PM

Help!

Am I the only one that experienced this 1 PX shift issue with IE 8 using this example?

I have my code working fine in all required browsers, except IE 8 due to this shift upon clicking my button.

I have searched high & low to no avail. Does anyone else have this problem and know of a way to solve this 1 PX shift in IE 8. My example is posted. All you need to do is rollover the button and press in IE 8 and look at the far right side shift upon click.

I really want to implement this solution for a project at work, but it won’t pass with the current IE 8 issue.

Any feedback would be greatly appreciated!

Comment by Tim Wilson on 09/01  at  07:54 PM

I really want to implement this solution for a project at work, but it won’t pass with the current IE 8 issue.

Comment by منتديات on 09/06  at  05:31 AM

I am seeing a 1 pixel shift on the right side of the button in IE8 and all looks well in Chrome.

Comment by مركز تحميل on 09/06  at  05:32 AM

@Tim Wilson: The best option I’ve found to fix the 1px background shift in IE8 is using Microsoft’s CSS vendor extension (which work in IE8 but not previous versions). I’ve documented a solution here: http://bit.ly/NSd0b.

Comment by Cory Duncan on 09/06  at  07:56 PM

Small comment (als0o send via Mail):

If you klick on the Buttons in Opera and IE8 there is a browser-build-in
moving of the span/button of 1px to the lower left. I figured out a
solution for that and put it into my code:

// IE8 (via conditional comments put this into the code)
button:active {background-position: 100% 1px; position: relative; left:
1px; padding-left: 1px;}
button:active span {left: -1px;}

// Opera
button span:active {top: -1px; left: -1px;} /* Now, also Webkit moves
the button, so extend your hack: */
@media screen and (-webkit-min-device-pixel-ratio:0) { button span {
margin-top: -1px;} button span:active {top: 0px; left: 0px;}}

Regards,

Oliver

Comment by Oliver on 09/06  at  09:26 PM

Thanks for the Article.

I’m guessing that there is still no fix for having this compatible for *readers who wish to browse with images off*

Do you know how i can overcome this?

Thanks
Jim

Comment by jim on 09/28  at  04:32 AM

Hi-

Last year I finally released my button script called Simply Buttons.  I recently released v2, I think you guys might like what I have, some of my earlier experiments are eerily familiar to this technique.

http://www.p51labs.com/simply-buttons-v2/

Thanks,

Kevin

PS. Simple Buttons does have a fix for the “shifting pixel” as well ;)

Comment by Kevin Miller on 11/17  at  08:58 AM

Extremely helpful article. I had read another Sliding Doors tutorial that used anchors instead of buttons and was scratching my head trying to figure out how to make IE play nice. The Safari/Chrome fix was helpful too!

Thanks again!

- Erich Musick

Comment by Erich Musick on 11/20  at  12:04 AM

None of the above IE8 fixes seemed to work perfectly, but playing around I found that this combination works:

button.submitBtn:active {
-ms-background-position-y: [the ‘correct’ position - 1px] /*replace expression with value correct for your sprite */
}

button:active {
position: relative;
left:1px;
padding-left: 1px;
}

button:active span {
left: -1px;
}

So that’s working, but :active state not working for me in IE7.  Ideas?

Thanks!

Comment by Tim Sheiner on 12/02  at  11:37 PM

Whoops, this declaration above:

button:active {
position: relative;
left:1px;
padding-left: 1px;
}

SHOULD BE

button:active {
position: relative;
left:1px;
}

Comment by Tim Sheiner on 12/02  at  11:40 PM

And the answer to the IE7 :active issue:

The :active pseudo-class is most often used with the a element. Windows Internet Explorer 7 and earlier only support using the :active pseudo-class with the a element.

Comment by Tim Sheiner on 12/02  at  11:44 PM

Please update the CSS in your article.

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

When it should be:
button::-moz-focus-inner {
padding: 0;
border: none; /* overrides extra padding in Firefox */
}

It appears you copied this incorrectly after the post from mstudio.  With the fix the buttons look good in Firefox 3.5.5

Comment by Richard Aday on 12/09  at  04:24 AM

Hi, I have created a version of this and have found that it works well, accept for a spurious amount of padding between the two images in Webkit. I have compensated for this by increasing the width of the right hand image, the only downside to this is it means the text label no longer appears central to the button, I think your example produces the same result although it looks less pronounced than mine:

http://www.jeremydalgarno.com/images/buttons.png

You can see a corrected and uncorrected version and can see how the text is shifted. Do you think there is solution to this? We can remove this extra padding in IE and Mozilla but not currently in Webkit?

Thanks.

Comment by Jezz on 12/17  at  12:48 PM

Hi
Tried this with a new Mac-look sprite. It looks wonderful in ALL browsers.
Congratz guys!

Comment by Yoke Lee on 01/08  at  11:10 AM

Just a note, your CSS doesn’t have any “focus” or “active” states, so keyboard navigation is a bit hard to pick up (e.g. tabbing through the web page doesn’t actually highlight your sample buttons). Otherwise very nice work.

Comment by Xander on 01/11  at  07:41 AM

So, when using the Safari/Chrome conditional below:

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

My code works fine and looks beautiful via DreamWeaver run locally, however when I upload my css to the server via Visual Studio 2010, the following code is no longer recognized or visible when using firebug in firefox to track down the problem.

Has anyone ever experieinced this issue with the Safari/Chrome hack?

Any help is greatly appreciated as I have exhausted all of my resources......

Comment by Tim Wilson on 01/12  at  10:47 PM

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

current versions of Safari(4.0.4 Mac) and Chrome do not need this, but looks like Safari(4.0.4 Win) does

anyone got a nice fix?

Comment by Jennie on 02/11  at  03:28 PM

As a follow on, depending on your zoom level the two sides don’t always match up on the iPhone (but you could send css3 styling of -webkit-border-radius, -webkit-box-shadow and -webkit-gradient instead)
nice example over on 24ways for some ideas

Comment by Jennie on 02/16  at  03:20 PM

Hey! i am facing a problem on this page in IE8 http://www.avtodeli.info/?c=user&action=login you will se two buttons, expecaly the right one is tricky. And only IE8 is cousing a problem. Have any sollutions?  ThX

Comment by Edvard on 02/18  at  01:40 PM

Loving this concept, however…

although the buttons look consistent across browsers when the page is static, when you actually use the page and click the buttons you’l notice that internet explorer has an ‘on click’ effect on the <button> which makes it appear as if it is being pushed down. This effect makes the background images of the <span> and the <button> misalign and appear broken.

So my question is does anyone know of a method that would disable this ‘on click’ effect?

Comment by Philip Hillman on 03/02  at  04:42 PM

I have found that in some cases,

button::-moz-focus-inner {
border: 0;
}

needs to be

button::-moz-focus-inner {
border: 0;
padding: 0;
}

In order to prevent Firefox from adding an extra 2px left and right padding to the button element.

Comment by Greg Johnson on 03/04  at  08:29 PM

This worked for me with Tim Sheiner’s second comment on 12/02

Comment by AL on 03/10  at  01:13 PM

I would like to add an extra image to this so that the buttons can have an icon with the text.  So far, I have manged to add an img tag inside the span, but the background sprite gets off by 12px on the enclosing tag (button here, I’m using an ‘A’ tag) Has anyone manage this?

Comment by David Morton on 03/14  at  11:12 PM

With the fix for IE and Opera it works perfektly for me! THX!!!!

Comment by Bravehartk2 on 03/17  at  05:05 PM

Thank you for this fix.  I would never have figured it out on my own....

Keep up the good work!

Comment by Corto on 03/30  at  03:03 PM

thank you for share it

Comment by 婚紗攝影 on 04/07  at  08:24 PM

This worked for me and fixed the 1px difference between right and left ‘part of the button’ so far IE6 + IE7 + IE8 + FIREFOX + CHROME:
button:active {
-ms-background-position-y:-49px; (-correct position -1 :: height is 48px)
#bottom:0px;
_bottom:-1px;
}

Comment by Bart Calixto on 04/09  at  09:16 AM

Thanks for the post. I found this in http://speckyboy.com/2009/05/27/22-css-button-styling-tutorials-and-techniques/ and used it for my project: http://food-prints.appspot.com/nutrients. Besides making it smaller, I also added

button.submitBtn:active span {
line-height: 1em; /* push text down */
}

Thanks!

Comment by Sargis Dallakyan on 04/19  at  09:05 PM

Thanks for the Chrome hack.
Although it makes me soo angry that we have to use hacks for every little thing in every browser. I want my time back!

Comment by Claudius on 04/27  at  03:15 PM

Thanks Greg Johnson! That fixed the 2px padding issue I was having in firefox!

Comment by Matt Rittman on 05/17  at  04:49 PM

maybe this will be good without javascript…

Comment by ryan on 06/08  at  08:35 AM

Can anyone help me. I’ve created my own buttons and set them up using this technique, it’s great. How do I have them as an <a> instead of a button. I want the buttons to be links to navigate around a website. Please give me some advice or an example.

Thanks so much!

Comment by Darryl Young on 06/11  at  01:40 PM

I am looking at your tutorial in IE8 on Windows 7 and the buttons exhibit the left/top 1px shift when clicked. I am running Windows 7 under Parallels/OS X but I don’t think that makes a difference.

Comment by werner on 06/24  at  02:49 AM

From what I’ve checked it works very fine, except one problem - Safari 4 has exactly same problem that Firefox had - it adds 3px padding on the right side of a span element. It can be fixed using
button span {margin-right: -3px;}
in safari/chrome section. But since this bug applies ONLY to safari 4, as both safari 3 and chrome are ok, this causes span and button background to overlapin the later two browsers, which is would be more-less fine in case of gif/jpg, but when using semitransparent png’s, that overlapping is visible.

Comment by Viktoras on 07/02  at  12:33 PM

thanks!

I’m on the way but that stupid margins in FF make me go crazy. That -moz-focus-inner invention is just silly.

again, thanks

Comment by MP on 07/23  at  10:24 AM

Can any1 help me with my query??
background-image of a button is not getting displayed in IE8 for Win7

Comment by Kavita Modi on 08/02  at  12:28 PM

just to follow up. I found that the left/top 1px shift only occurs when the submit button click is intercepted by jQuery. It doesn’t do it when IE8 is in IE7 mode.

Comment by werner on 08/04  at  03:16 AM

I have managed to get these buttons working now in most situations but I was having the same problem a lot of you had in IE8 - when clicked (active) the ‘end piece’ of the image shifted slightly up and left. I’ve fixed this with “-ms-background-position” but I noticed a weird problem. If I click AND drag off the button, the ‘end piece’ shifts down and right slightly. This isn’t really a big problem, I just wondered why… :)

Comment by david on 08/18  at  12:16 PM

1px IE8 problem can u help me plz?

Comment by yashpal on 08/19  at  09:17 AM

i have 1px problem with IE8 and active problem with IE7 plz help me
Here is my css code

button {
position: relative;
outline:none;
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:bold 14px Arial, Helvetica, sans-serif;
text-align: center;
background: transparent url(btn_blue_sprite.gif) no-repeat right -162px;
}

button.submitBtn span {
padding:11px 0 0 15px;
height:25px;
background: transparent url(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 -216px;
}

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

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

button.submitBtn:active span, button.submitBtnHover span {
background-position: 0 -108px;
}

Comment by yashpal on 08/19  at  09:20 AM

Hi! Here’s another quick IE8 active fix: (You might have to modify the padding and the backgroundposition values so it fits your button size. Also, the outline declarations isn´t nessessary but it looks nicer. )

<!--[if IE 8]>
<style type="text/css">
button.submitBtn:active {padding-right:16px; -ms-background-position-y: -209px; outline:0 }
button.submitBtn:focus {outline:0 }
</style>
<![endif]-->

Comment by Jonas on 08/23  at  11:53 AM

Has anyone fixed this for Safari 5 for Windows?

In the Safari media query, curiously Safari (5.0.2) for Windows also needs a margin-right: -3px to remove the right gap. However, that also causes an overlap on Safari 5.0.2 for Mac.

Anyone have any ideas?

Comment by Tim Kelty on 10/14  at  12:26 AM

Hey,

Great work, but there is this tiny thing I would like to add. ( if it is not said yet.. )
To avoid IE7 “cut off” problems with letters like “g” ( for example “Log in” ),
then just use “line-height”. Give both “line-height” and “height” the same value, for example:

button.submitBtn span {
padding: 13px 0 0 15px;
height:37px;
line-height:37px;
}

Now you may need to play with the first (upper) padding to get the text in the center and also depends on what size is your font.

Good luck.

Comment by Henri on 11/29  at  10:02 PM

nice really cool..
it’s most cool button i have ever used.

Comment by abhimanyu on 12/02  at  10:22 PM

Even with the IE8 fix mentioned above, I am still noticing a 1px shift to the left on these buttons. The y-axis shift has been fixed, but not the x-axis shift. I think the reason is because the affected element is right aligned. I’ve tried several options, to no avail, with adjusting this right positioning. So I put in some IE8 conditional CSS and swapped the position of the background elements. I know this doesn’t work well in FF or Chrome, but it fixes the onClick/active shifts of the button element in IE8:

[[ CODE:

<!--[if IE 8]>

button.primary
{
padding: 0;
background: url( ‘/skins/ecommerce/resources/images/bg-button-2.gif’ ) no-repeat left top;
}

button.primary span
{
padding: 6px 15px 0 15px;
background: url( ‘/skins/ecommerce/resources/images/bg-button-2.gif’ ) no-repeat right -40px;
}

button.primary:active
{
-ms-background-position-x: 1px !important;
-ms-background-position-y: -79px !important;
}

button.primary:hover, button.primaryHover
{
background-position: left -80px;
}

button.primary:hover span, button.primaryHover span
{
background-position: right -120px;
}

<![endif]-->

However, I havent’ been able to find a fix yet for two remaining issues:

1. The button experiences a pixel shift in Chrome when you increase the page Zoom.
2. The button experiences a pixel shift in IE8 if, when you click on the button, you don’t release the mouse and drag in any direction.

Has anyone found a fix for these yet? Thanks!

Comment by Rob on 12/03  at  10:58 PM

Is this still relevant information for how to create CSS sliding doors for buttons. I ask as i’m wanting to implement this into my website but not sure whether there is a new way to do this now. As i note this post is from 2009

Comment by Reclaim PPI on 12/30  at  02:01 AM

You don’t actually need to separate the left button background and the right button cap image. You can just have a single long button and use it as the bg image. Saves some space on your sprite. :-)

Comment by Cre8ive Commando on 01/20  at  01:39 AM

wow, good work need to take a look at this… I got a very interesting idea of this!

Comment by Fredrik on 01/21  at  12:55 PM

This is really great. I am planning to use on all future clients if they’ll accept rollovers in their creative. Well done!

Comment by Neil on 02/15  at  09:33 PM

Thanks for this great tutorial. Just what I was looking for :)

Comment by J. Hendrix on 03/18  at  02:52 PM

This appears to have removed any action for when you click the mouse, or does this have to be manually implemented?

Comment by Dave on 03/31  at  05:59 PM

Sorry, there was a bug in my previous comment:

The CSS for the webkit and opera fix should look like this:
/* fix webkit & opera */
.webkit button.button-light span,
.webkit button.button-dark span {
margin-top: -1px;
}

.opera button.button-light:active span,
.opera button.button-light span:active,
.opera button.button-light:active span:active {
left: -1px;
top: -1px;
}

But still there are two bugs mentioned in previous comments (hovering while not realeasing clicked button under IE8 and zooming under chrome) - but I guess we’ll have to live with that.

Comment by Tom on 05/21  at  12:23 PM

The problem with your implementation is that a modern web UI must show multiple states.  Your design does not have any way of showing a disabled state.

Comment by Simon Golding on 05/28  at  11:33 AM

Commenting is closed for this post.

Book cover: Designing with Progressive Enhancement

Enjoy our blog? You'll love our book.

For info and ordering: Visit the book site