Background Position X and Y

Every now and then I look at using background-position-x and background-position-y but can never seem to find a definitive and up-to-date resource. To save myself the trouble in the future, I'm documenting it here.

Positioning via separate X and Y values is a feature that Internet Explorer introduced but never made it into a W3C specification. Any recommendations to add it to the spec have been denied.

Why have separate X and Y values?

I believe that there are several reasons why you may wish to have separate values.

Animation

The last time I was frustrated by the lack of consistent cross-browser support for X/Y was when I wrote my article on animating background images using jQuery. Having to take a string value, split it into its separate X and Y values, parse the units, and then rebuilding the X/Y value into a single string is a cumbersome experience. Being able to animate just the X or Y value would have been much simpler and would have worked with jQuery "out of the box", since jQuery already knows how to animate pixel or percentage-based values.

Sprites

CSS Sprites have become a popular way to optimize the performance of a page. It's an interesting technique in which you compile numerous background images into a single image and then use background-position to only show the desired part of the image on an element.

#a { background: url(sprite.png) 0 0 no-repeat; }
#b { background: url(sprite.png) 0 -30px no-repeat }
#c { background: url(sprite.png) 0 -60px no-repeat }

Of course, we could optimize this like so:

.icon { background: url(sprite.png) 0 0 no-repeat; }
#a { background-position: 0 0; }
#b { background-position: 0 -30px; }
#c { background-position: 0 -60px; }

However, given access to separate X and Y values, we could optimize it like so:

.icon { background: url(sprite.png) 0 0 no-repeat; }
#a { background-position-y: 0; }
#b { background-position-y: -30px; }
#c { background-position-y: -60px; }

Admittedly, that didn't save us any bytes and for this reason alone, I can see why the W3C denied the inclusion of this into the specification.

Internationalization

However, let's take a look at internationalization. Specifically, in having to deal with right-to-left (RTL) environments like Arabic. In these scenarios, where an icon is positioned on the left of some text in a left-to-right environment (LTR), the icon should now be positioned on the right.

Wouldn't it be great to just add in an extra line in bidi environments where we tell the background of all sprites to be positioned on the right instead of the left?

html[dir=ltr] .icon { background-position-x: 100%; }

That's it. One line. (And this actually works in IE7+, S3+ and Chrome.)

Instead, without the ability to separate X and Y values, all sprites need to be redeclared for RTL environments.

Support Table

Finally, here's the support table for which browsers support background-position-x and background-position-y.

Browser Version
Opera No Support
Firefox No Support
Safari 3+
Internet Explorer 4+
Chrome Yes

Opera is the only hold-out at this point and hopefully we'll see it get introduced at this point. It has become a de facto standard and it's exclusion from the W3C specification doesn't diminish it's usefulness.

I'm embarrassed. I could've sworn I had it working in the latest version of Firefox but I've re-run my test case and I can't get it working in Firefox at all. My apologies for poor testing. But I'd still like it in all browsers, pretty please!

Published March 02, 2010
Categorized as HTML and CSS
Short URL: http://snook.ca/s/971

Conversation

34 Comments · RSS feed
Stephanie Sullivan said on March 02, 2010

I completely agree! Estelle and I had a discussion about this just last night as we were reading the specs and realized this didn't make it in. Quite a shame. It's extremely useful. Thanks for writing this up Jonathon. :)

Rob Glazebrook said on March 02, 2010

You forgot one selling point: Finally being able to know, without having to look it up for the 4,038th time or guess blindly, where the X-value and Y-value go. I can never remember whether X or Y comes first, and I always resort to guessing randomly. Defying all logic, I'm wrong far more than 50% of the time.

Estelle Weyl said on March 02, 2010

I find background-postition-x and y very useful for sprites. For example, with a rollover background image change, using a sprite, you can just do a :hover {background-position-x: -20px;}, so you only have to declare the default state of the background image. With one line of code, every bg image, on hover, will move over Xpx, showing the hover state in a well laid out sprite. Without background-position-x and y, I have to declare every single hover state separately.... taking many more bites.

You list FF as supporting, but my grid at http://www.standardista.com/css3/css3-background-properties shows lack of support in FF. I am testing FF 3.5.8.

Jonathan Snook said on March 02, 2010

@Estelle Weyl: Thank you for pointing out the lack of support in Firefox 3.5. I've updated the support table accordingly. And indeed, hover/active states is another good reason to have X/Y support.

jamEs said on March 02, 2010

Just thought I'd mention that your website makes Firefox 3.6 for Mac crash hard. Tried loading it twice. Pretty sure I've tried accessing your site previously and the same has happened. Using Chromium on my Mac does work though.

George said on March 02, 2010

I can't count how many times I've wanted to use this when I'm using the sprite technique, not realizing that it's now widely supported (Firefox 3.6 seals the deal).

Thanks for the info!

Mike said on March 02, 2010

Completely agree that this should be in the spec. I was looking at it for a page of logos, would have been perfect for the sprite and it would have cut my CSS code in about half the original way I was coding it (ending up going a different route sans sprite for ease of updating, which saved code bytes as well, just more server requests.)

Anyways, glad to hear that all of the major browsers now support this (bar Opera) and it's actually one of the few things we don't (shouldn't) have to worry about older versions of IE.

Helen said on March 02, 2010

Bob (#2), this is a cosmic law which also applies when inserting a piece of paper in the printer for duplex printing. I always get the two prints on the same side and I always mix up X and Y when positioning backgrounds.

Amber Weinberg said on March 02, 2010

Background x and y positions are pretty confusing at first, and to this day I still get them mixed up in the shorthand (which one goes vertical and horizontal), however after getting the hang of them, sprites are pretty quick to implement now.

philippe said on March 02, 2010

Mr Snook,
Do you have a test case that actually shows this as working in Gecko 1.9.2 + (firefox 3.6+) ? Because my testcases fail for both the -moz-background-position-* and background-position-* – and the error console flags them as errors (tested with both fx 3.6 and the latest Minefield builds).

Jonathan Snook said on March 02, 2010

@Philippe: I have no idea how I managed to screw that up but I've updated the article to reflect the cold hard fact that I was wrong. Sorry.

philippe said on March 02, 2010

@Jonathan: Errare humanum est…
I was already paranoidly afraid that my goldfish had managed to cause all my computers to malfunction in some most bizarre ways. Glad that this is not the case :-).

Kit Grose said on March 02, 2010

Admittedly, that didn't save us any bytes and for this reason alone, I can see why the W3C denied the inclusion of this into the specification.

I disagree completely. Here's where it saves space:

.icon { background: url(sprite.png) 0 0 no-repeat; }
#a { background-position-y: 0; }
#b { background-position-y: -30px; }
#c { background-position-y: -60px; }

.icon:hover { background-position-x: -30px; }
.icon:active { background-position-x: -60px; }

Which sure beats:

.icon { background: url(sprite.png) 0 0 no-repeat; }
#a { background-position: 0 0; }
#b { background-position: 0 -30px; }
#c { background-position: 0 -60px; }

#a:hover { background-position: -30px 0; }
#b:hover { background-position: -30px -30px; }
#c:hover { background-position: -30px -60px; }

#a:active { background-position: -60px 0; }
#b:active { background-position: -60px -30px; }
#c:active { background-position: -60px -60px; }

Imagine that across an entire spectrum of sprites (usually many more than 3) and at the very least, it's not easy to keep track of the crap you're coding. Making a change (based on a change to the underlying art) is especially frought with danger.

petr said on March 03, 2010

Interesting is, that setting background position in JavaScript using jQuery, background positioning works just fine for me even in Firefox 3.0.10 and also in Opera 10.00. One my jQuery plug-in is relying heavily on background positioning and so far it is performing well everywhere I've tested.
Maybe jQuery performs some kind of magic under the hood to make it happen.

Piotr Petrus said on March 03, 2010

Admittedly, that didn't save us any bytes and for this reason alone, I can see why the W3C denied the inclusion of this into the specification.

I laughed out loud, because — sadly — this might be true. That’s what happens when engineers don’t listen to designers when building a spec.

Andy Kinsey said on March 03, 2010

Love this explanation of how it works, i've recently experimented with background positioning on my site (click my name) - I find it works in most current browsers but even with the various scripts around nothing will get it to work in older browsers, its pretty much same story with multiple image backgrounds that i'm growing to love so much - by the way IE8 doesn't even support these never mind 7 or 6! Pfft

Jon Raasch said on March 03, 2010

Yeah I'm in your corner and have been clamoring for this as well.

Ryan Cannon said on March 04, 2010

Admittedly, that didn't save us any bytes and for this reason alone, I can see why the W3C denied the inclusion of this into the specification.

That's certainly true when your selector is #a {}, but when you're doing something like #doc .header .content-navigation li {} adding hover states and selected states then doing three rules each it starts to add up. Plus, managing those sprites is a nightmare.

Jason Grant said on March 09, 2010

I always get the x and y values the wrong way round initially when coding the background image into anything. :-)

Nicolas Chevallier said on March 09, 2010

Thanks for this little tips. I never thought about that but it will save me a lot of time for my new project!

Niels Matthijs said on March 10, 2010

"Admittedly, that didn't save us any bytes"

Hmmm, who cares. The point is that you didn't have to declare the same Y-value three times. If the Y-value changes you have to adapt it in three places, by being able to simply change the X-value, you gain control and there's less room for errors when adapting the css.

Nora Brown said on March 10, 2010

I'd love to have this feature as well. For large sprites, it would make the CSS much more compact and easier to manage.. C'mon Firefox!

Nicely implemented comment preview, by the way.

Jake said on March 13, 2010

It does actually work on Firefox, at least for me it does. Try a fresh install?

Dena said on March 18, 2010

I use sprites a lot for web sites with a lot of images so there can be minimal requests. But i think it's currently fine with current background-position property. In fact, i havent heard of this x-y thing before this article Jonathan :)

Russell Heimlich said on March 19, 2010

I wish background-posiiton-x and background-position-y were universal. They are such a good idea. Here is the perfect use case of where such a feature would come in handy. Instead I had to resort to much more bloated code for a card game that utilized sprites http://www.russellheimlich.com/blog/ie-gets-a-css-rule-right/

Eva said on March 25, 2010

I concur Jonathan. So many times I've been frustrated to have to get both the X and Y value when i only need to alter one at a time. Shame it didn't pass w3c specifications. I'd love it to have cross-browser support...

Marton Sari said on March 28, 2010

+1. We need it. Inexpressibly blind those spec makers are...

Burton Radons said on April 03, 2010

I'm just banging my head on this issue myself and the very existence of it is absurd. There's no need for a "use case". background-position is a property with multiple values. It should be split, as every other property with multiple values should be, for the same reasons - because sometimes you need to splice CSS in interesting ways that can't be foreseen. If giving all compound properties single-property alternatives isn't policy for the design of CSS, then it must become so. Do not prescript.

This worthless issue has wasted hundreds of times the man-hours it would take to just put it in the standard and have Firefox implement it properly.

It doesn't work in FF 3.6.3 for me, and "-moz-background-position-[xy]" don't seem to exist. I'm not going to try a fresh install or anything like that because if it happens to me, it's going to happen to other visitors so I have to assume it's broken. I guess I'll just need to add ... 20x the cases, woo!

Benjamin Cordes said on February 05, 2011

Thank you so much! I've been cross-browser debugging my site and could not for the life of me figure out why Firefox wasn't honoring the "background-position-y" in my CSS file, and here I come to find it's not supported and all I need to do is remove the "-y" to get things working. Thanks again for inadvertently saving me hours I'd have otherwise spent doing countless Google searches; keep blogging!

Javier Albinarrate said on February 11, 2011

This feature is SOOOO much wanted, it is a pitty that it is not standard. Basically in my case I have a number of different bar styles (distributed horizontally one next to the other) with different discrete levels vertically stacked (lets say 5% 10% and so on).

If I could manage X and Y independently, then, one dimension (X) would be the bar style defined by a class, and the other dimension (Y) would be the percent of the bar.

So right now, I have to manually manage both X and Y as property... every time I want a BLUE bar... I have to lookup, what X corresponds to blue... that sucks.

Regards!

Julian said on March 02, 2011

I'm running into a place where I need this - the use case is an element with a background coming from a sprite image. I always want it to hover to

background-position: (current) -20px;

but I can't see how to just change the Y position!

Kevin Rice said on March 16, 2011

FIREFOX WORKAROUND (sprite, 1-axis movement):

#a {background-position:0px 0px}
#a:hover {background-position:inherit -100px}

Use of 'inherit' appears to work fine, and inherits the non-hover position without having to re-write it. Mileage may vary.

Kevin Rice said on March 17, 2011

FIREFOX WORKAROUND: SCRATCH THAT!!! IT DOES NOT WORK!

Testing error on my part. Apologies.

Aldo_MX said on March 31, 2011

Firefox developers are just neglecting to implement it because from their point of view it either breaks sites or breaks the spec, even with a vendor prefixed implementation:

https://bugzilla.mozilla.org/show_bug.cgi?id=550426

Please people help adding votes to increase the importance of the bug.

Sorry, comments are closed for this post. If you have any further questions or comments, feel free to send them to me directly.