I am trying to switch to the technique of 1 giant icons file. I didn’t like the opacity filter for the disabled elements. I really wanted grayscale. So I had to use duplicate images. I made a grid on my image so that the math was easy. See image here. So in my CSS, all I have to do is adjust the horizontal axis for the background-position. Internet Explorer does this with background-position-x. Firefox doesn’t support that! They just have regular background-position.
This blows. Now my css for this section is 3x longer than it needs to be. Bad Firefox. I usually don’t need to say that, but, well, there it is.
Unless there is a CSS opacity filter that shields out all the color? It would be a cool feature for IE8 and FF3!
Started in 1996, Glen Lipka has been been randomly publishing about User Experience, Technology, Human Psychology and other subjects.
39 Comments
commadot.com » Blog Archive » The right sprite?
August 11th, 2007 at 3:44 pm
[...] is that this method creates alot of CSS defintitions that are hard to manage. The reason is that Firefox does not support the background-position-x CSS attribute. This really sucks because it means that you can’t have a sprite ‘matrix’ that [...]
Bryan Buchs
August 13th, 2007 at 1:35 pm
Firefox doesn’t “fail” background-position-x/y! That’s a MSIE specific CSS property.
“…Microsoft introduced two new, browser-specific background properties with the release of version 5.5 of Internet Explorer: background-position-x and background-position-y…”
http://safari.oreilly.com/0130092789/ch14lev1sec7
Glen Lipka
August 13th, 2007 at 2:24 pm
I understand. But it’s such an obvious feature to have. I really think Firefox dropped the ball by not implementing it. This is where standards and common sense do not always match. In my mind, they fail the common sense test. And when I try to use the feature, it fails to work.
Stuart Steel
August 14th, 2007 at 1:12 am
re: standards.
I agree with Glen. While standards are a fantastic idea, and to be supported, being too blinkered about them can be limited. While web standards and standard compliant browsers are usually the good guys its also important to recognise when companies like microsoft implement something of quality and commonsense. Hopefully the standards will follow.
erkko
August 17th, 2007 at 8:54 am
what’s with a moaning? 3x longer css? how come?
background-position-x: 300px;
background-position: 0 300px;
so, where’s the three times longer css? Any example of your code to illustrate this claim? not to mention first example is clearly no-css/ie-only and second is as old as css1
Glen Lipka
August 17th, 2007 at 3:46 pm
Sample code and more detail:
http://commadot.com/?p=590
andy
January 16th, 2008 at 4:13 pm
erkko, thats only assuming you want the background’s y position to be at zero. What if it is at a variable y position? Without changing the X only, you would have to use redundant logic to find the Y again.
Renato
January 23rd, 2008 at 6:18 am
I was searching just to find this same issue.
I am using CSS Sprites, which is a great performance technique, and I’ve got really disappointed with Firefox because of this…
For those who not understood what is the real issue, try to imagine this situation…
I have one image with a lot of logos which I just use background-position to place to the right location of my div. But I do not want that all of my divs have the same appearance. For this kind of situation, I want that sometimes the logo can be placed at the left and sometimes at the right…
HTML CODE
HERE I WANT ONE LOGO TO THE LEFT
HERE TO THE RIGHT
CSS CODE
/* default background position to the left */
div{background:url(logos.gif) no-repeat;}
/* set background position to the right */
div.customdiv{background-position-x:right;}
/* positioning the logos */
div.logo1{background-position-y:-10px;}
div.logo2{background-position-y:-50px;}
If I use the standard and firefox logic, I cannot use the background-position-y nor the background-position-x. I’d have to make a redundant logic to all position both at the same time…
background-position:right -50px;
background-position:left -50px;
ALWAYS… Sorry, I hate to say this, but this time MSIE won.
Glen Lipka
January 23rd, 2008 at 9:14 am
@Renato: Hmm, I wonder if FF3 allows independant background positions? In the meantime, check out fofreground sprites. They do othe trick very well.
http://commadot.com/the-right-sprite/
Anon
March 6th, 2008 at 12:33 pm
Andy wrote: “erkko, thats only assuming you want the background’s y position to be at zero. What if it is at a variable y position? Without changing the X only, you would have to use redundant logic to find the Y again.”
“background-position: 0 300px;” was an EXAMPLE!
You can make what you need…
background-position: 150px 300px;
background-position: 300 0px;
background-position: 100% 100%;
background-position: 45% 93%;
They all work and they only are one line of CSS.
@Renato: you just need to specify both the x and y of your div.logo1 position (i.e., drop the “-y” and just add 0 for the “x” position.
Jonas
March 19th, 2008 at 7:06 am
I’m having the same problem, I have a menu with a big bg image for all the links.
Then i have a set of rules that sets bg pos x/y for every link.
Then, because of Firefox, what could have been #nav a:hover { background-position-y: -25px; } for ALL the links, now have to be another set of rules for every link, to set both positions right.
And then a third set for the active state.
And bg pos x/y is valid CSS3, BTW.
Paul Tierney
April 9th, 2008 at 2:49 am
background-position-x: left; should be
background-position: left 100%;
background-position-x: right; should be
background-position: right 100%;
its all very simple.
Glen Lipka
April 9th, 2008 at 7:40 am
Paul, I am not understanding your comment. The goal is to declare X/Y coordinated INDEPENDANTLY. That means that one css line can control a column in a background sprite matrix with many columns and many rows. Without independant declaration, there is no way to use a matrix as a background image. I have a separate post about foreground-images which can use margin-left and margin-top to achieve the desired goal.
Unless, I am misreading and you are referring to one of the followup posts.
Troy III
June 12th, 2008 at 11:25 am
I’ve just checked my page that has in use a background-position-x and/or -y @ CSS level 2.1 at their validation site. After seeing a green safe bar it offered me icons that this page is CSS2.1 Valid and certified.
Now I really don’t understand – what are they checking there for? A well formed text or CSS declarations?
Or does this mean that background-position-x/y is CSS 2.1 standard?!!
Or does this mean that we should wait another decade for W3C, to come to their “own brilliant idea” that is should be very useful to be able to position background x/y positions separately. Therefore we propose a new CSS invention: background-placement-horizontal: 16px-to-the-right/left; and
background-placement-vertically: 25px-tho-the-top/bottom;
or some other goddamn novel-length statements, like their famous: document.getElementBy(‘theID”).style.backgroundPlacementVertically=
25pxToTheTop, with a warning: “be sure not to forget to explicitly state the “ToTheTop” instruction as indicated otherwise the browser will completely ignore your instruction since the browser will not know the direction which way to push the background image.
Well. So much for the standards and lazy browsers like Mozilla’s or should I say, Godzilla’s…
Glen Lipka
June 12th, 2008 at 2:54 pm
I just tested in Firefox 3. Still no support although there was some rumblings about support using the mode here: http://archivist.incutio.com/viewlist/css-discuss/74335
I just realized that all of my examples have moved. Sorry about that.
Shivam
September 17th, 2008 at 9:32 am
Guys this works!:
The syntax for setting the background x and y properties is:
background-position: [horizontal position] [vertical position];
Such as:
background-position: right top; //places the image right horizontally and top vertically
background-position: left bottom; //places the image left horizontally and bottom vertically
background-position: center center; //places the image center horizontally and center vertically
..it’s really simple.
Glen Lipka
September 17th, 2008 at 9:40 am
Shivam, please read the post more closely.
I am trying to set the Y position independantly of the X. In other words, I want background-position-y, not X, not both. Your answer, unfortunately, is not helpful.
The reason to want to do this is to use a background sprite as a matrix where you could change columns without changing the row. That way you could have icon “states” without an explosion of CSS for every single matrix x-y position.
Greg Tczap
September 29th, 2008 at 11:10 am
I am currently dealing with this same problem – it has been frustrating to say the least. I find it slightly pathetic that there exists no standard CSS properties that allow you to define the background image on the x and y axis separately. However, I don’t see this as a failing of Firefox, because they are following web standards and there is no such properties as background-position-x and background-position-y in the official CSS specs. Perhaps there should be – but that is an argument that should be directed at the W3C and not at Firefox.
Anyways, here is my initial idea for a solution. Why not just write your own javascript functions to change the x and y positions? This could be done in two generic functions so as to hide the complexity of this operation. For example, a changeYPos(myElement, newPos) function could parse out the current x AND y positions for the background image of the element, and then set the Y of the background position by passing it the old x along with the new y. Then that function could be re-used and it would be relatively easy to create cross-browser compatible image matrix using this technique.
Glen Lipka
September 29th, 2008 at 11:42 am
@Greg: Interesting solution. That could even be made as a jQuery plugin, for example to make it easier.
Greg Tczap
September 29th, 2008 at 12:02 pm
@Glen: Here is an example of a function I just wrote to do this. I have not tested it extensively across all browsers but it seems to work fine so far in FF3.
function changeBackgroundPosition(element, axis, value)
{
var oldPos;
var newPos;
oldPos = document.getElementById(element).style.backgroundPosition;
alert(“oldPos = ” + oldPos);
if (axis == “x”) {
newPos = oldPos.replace(/^\S+/, value);
} else if (axis == “y”) {
newPos = oldPos.replace(/\S+$/, value);
}
document.getElementById(element).style.backgroundPosition = newPos;
}
jameal
November 23rd, 2008 at 6:29 pm
I didn’t bother reading any of the other comments, so I don’t know if someone else posted this, but I also had this same problem and solved it this way:
background-position: 0% -40px;
Just use 0% for whichever axis stays the same!
jameal
November 23rd, 2008 at 6:31 pm
Actually, that didn’t work. Nevermind, haha.
Glen Lipka
November 23rd, 2008 at 6:35 pm
@jameal: Man, you almost had me there. My heart started beating faster.
I’ve been working on a product where high speed and no-IE6 is ok. It’s so freeing to ignore IE6 and not bother with sprites. I just use a single PNG file and call it a day.
Nathan Clark
January 7th, 2009 at 6:56 am
This recreates the background-position-y, allowing for independent declaration:
You could obviously swap that around to change on -x if you wanted.
Ethan
March 17th, 2009 at 6:31 am
Hello. I apologize in advanced if this has been already posted by somebody else. I too, was looking for the problem regarding the missing backgroundPositionX property.
Instead of that I use
parseInt(document.getElementById(“myElement”).style.backgroundPosition.split(” “)[0]) to get X and
parseInt(document.getElementById(“myElement”).style.backgroundPosition.split(” “)[1]) to get Y.
Of course, before the values can be read, they have to be first assigned, somewhere in the javascript code with
document.getElementById(“myElement”).style.backgroundPosition = “10px 10px”;
as you can’t read the default values specified in css.
Ethan
Ethan
March 17th, 2009 at 6:32 am
split(” “)
space character.
SamGoody
April 30th, 2009 at 2:09 am
You are able to declare the x position independently in Firefox 3.01, but there is no way to change the y.
Many times, though, that is enough.
http://www.w3schools.com/js/tryit.asp?filename=try_dom_style_backgroundposition
background-image:url(bgdesert.jpg);
background-repeat:no-repeat;
background-position:25px center;
background-attachment:fixed;
…
function changePosition(){
document.body.style.backgroundPosition=\
Leon Poole
June 2nd, 2009 at 2:58 am
Glen I’m in the same boat as you and find it hard to understand why the ability to define background-position-x/y isn’t standard. They give your border-left, border-top, padding-left, bottom etc. – being able to define x or y uniquely seems to be the natural progression.
Would love a follow up on this if it ever becomes standard.
David W
September 6th, 2009 at 1:38 pm
I’m in need of the same thing – a way to independently set the X and Y background-positions independently (in different selectors) in Firefox + Webkit + IE 7+.
I tried:
.column-2{background-position-x:-16px;}
.row-2{background-position-y:-16px;}
and:
.column-2{background-position:-16px inherit;}
.row-2{background-position:inherit -16px;}
any other value (i.e. 0, 0%, 100%, top, left, center, right, bottom, inherit, etc) will override both axes of the previous selector — which destroys the purpose.
????
September 27th, 2009 at 5:55 pm
well, I search and hit here, frustrating reading down.
Finally I took this solution and it works:
function set_backpos_y(ele, val){
var posX = $(ele).css(‘background-position’).split(‘ ‘)[0];
$(ele).css(‘background-position’, posX+” “+val+”px”);
}
TempNameNr2346234
October 20th, 2009 at 11:44 am
The solution is to first set height = “100%”! It can also (only?) be done with javascript…
//…For example you set the background in fram x to bottom-right…
bFn = getElementsByAttribute(top.frames[x].document,”body”,”background”)[0];
bFn.style.margin = “0″;
bFn.style.padding = “0″;
bFn.style.width = “100%”;
bFn.style.height = “100%”; // <<< important
bFn.style.backgroundRepeat = "no-repeat";
bFn.style.backgroundPosition = "right bottom"; //x y
TempNameNr2346234
October 20th, 2009 at 12:35 pm
CHANGE background TO bgcolor !!! Somehow I missed to test the last change I made
Flavio Copes
November 15th, 2009 at 4:20 pm
Thanks, I solved a bug using the comments above:
background-position-x: -300px;
=
background-position: 0 -300px;
background-position-x: -300px;
background-position-y: 20px;
=
background-position: 20px -300px;
background-position-x: -300px;
=
background-position-y: 50%;
background-position: 50% -300px;
mStudios
November 15th, 2009 at 8:41 pm
What people don’t understand who state the setting the -x plus the -y at the same time is no big deal: I have a whole array of -y = top but on the -x axis they are all at different positions.
THAT is what makes the code so much longer, as now I have to write -x=50/-y=top and -x=25/-y=top and -x30/-y=top etc. etc. etc… that is A LOT more than just -y=top.
Glen Lipka
November 15th, 2009 at 9:19 pm
Agreed mStudio. I have no idea why the W3C never dealt with this and why Mozilla/WebKit dont either. It’s such a simple thing.
Ryan
December 4th, 2009 at 9:38 am
Webkit supports `background-position-x` and `background-position-y`. Firefox is the black sheep here.
Those who think it’s not an issue clearly have never optimized a website using sprites, and are unlikely to be gainfully employed in the web development industry
(you know it’s true!)
Alex
January 23rd, 2010 at 1:48 pm
Here is my solution for u’re problem:
You need to append this lines to the css:
background-attachment: fixed;
height:100%;
Cheer’s,
Alex Manolescu
Ahmad Alfy
January 27th, 2010 at 4:50 pm
I had my navigation like this :
#nav li a {
background : url(image.png) no-repeat;
}
and every a has an ID to specify the position and the width. I wanted to do
#nav li a:hover{
background-position-y : -35px;
}
and all will be fixed… Shame it fails on FF
Brandon
February 1st, 2010 at 1:20 pm
Want to break the background-position into x and y? Use the JavaScript split() function to break the string into an array so you can then use it dynamically. One line and you have the respective x and y coordinates for the background-position.
var bgpos = someObj.style.backgroundPosition.split(‘ ‘);
bgpos[0]; // x
bgpos[1]; // y