Investigation into cross-browser differences in background-position and variants in regard to jQuery.css()
This page, and the ones that follow, document how I investigated the different browser behaviours, first with tests and then with code changes to the jQuery core. For previous discussions see the following:
Initial Tests
I started by making a checkout of the jQuery subversion code as of Sat Nov 22 01:25:11 CET 2008 (revision 5949). I built a non-compressed version of jQuery using ant.
To the downloaded version of the test file http://jqueryjs.googlecode.com/svn/trunk/jquery/test/index.html I added the following code:
<style type="text/css" media="screen">
#bp { background: url('data/cow.jpg'); }
#bp2 { background: url('data/cow.jpg') 10px 1em; }
</style>
<div id="bp"></div>
<div id="bp2"></div>
According to the CSS 2.1 specs, the first CSS rule should set the background-position of #bp to 0% 0% (which can be specified as left top, top left, 0px 0px, etc.)
I then created a test suite of 9 QUnit tests (I add a few more tests at the end to make the final number 14) and ran it across a selection of the browsers jQuery supports. The test suite (.js format) is based on the objective of creating a consistent treatment of the background-position, background-position-x and background-position-y CSS properties whether specified as listed or in camelCase notation. The test suite also imposes a particular set of requirements:
- Report values as percentages instead of the named values of top, right, bottom, left and center (see test 9 below)
- Report zero values as 0% not 0px (or any other variation on zero)
- Do not convert other originally specified values to another unit of measure. For instance, using the setter
jQuery('#myDiv').css('background-position', "10px 1em"); should lead to the getter jQuery('#myDiv').css('background-position') returning "10px 1em" and not "10px 13px" even if the browser renders 1em as 13px.
- The setting a single axis (e.g., background-position-x) should be reported when subsequently getting the double-axis (e.g., background-position)
The initial results, before any code changes to the jQuery core.js were made:
1. jQuery('#bp').css('background-position') unspecified initial values (0% 0% according to CSS2.1)
| Assertion |
Firefox |
Internet Explorer |
Safari |
Opera |
| 1.5.0.12 |
2.0.0.18 |
3.0.4 |
6.0 |
7.0 |
3.2 |
9.62 |
| Assert default/initial value for background-position is 0% 0% |
"" |
"" |
0% 0% |
undefined |
undefined |
0% 0% |
0px 0px |
| Assert default/initial value for backgroundPosition is 0% 0% |
"" |
"" |
0% 0% |
undefined |
undefined |
0% 0% |
0px 0px |
| Assert default/initial value for background-position-x is 0% |
"" |
"" |
"" |
0px |
0px |
0% |
"" |
| Assert default/initial value for backgroundPositionX is 0% |
"" |
"" |
"" |
0px |
0px |
0% |
"" |
| Assert default/initial value for background-position-y is 0% |
"" |
"" |
"" |
0px |
0px |
0% |
"" |
| Assert default/initial value for backgroundPositionY is 0% |
"" |
"" |
"" |
0px |
0px |
0% |
"" |
2. jQuery('#bp2').css('background-position') initial values specified from css (10px 1em)
| Assertion |
Firefox |
Internet Explorer |
Safari |
Opera |
| 1.5.0.12 |
2.0.0.18 |
3.0.4 |
6.0 |
7.0 |
3.2 |
9.62 |
| Assert default/initial value for background-position is 10px 1em |
"" |
"" |
10px 13.3333px |
undefined |
undefined |
10px 13px |
10px 13px |
| Assert default/initial value for backgroundPosition is 10px 1em |
"" |
"" |
10px 13.3333px |
undefined |
undefined |
10px 13px |
10px 13px |
| Assert default/initial value for background-position-x is 10px |
"" |
"" |
"" |
10px |
10px |
10px |
"" |
| Assert default/initial value for backgroundPositionX is 10px |
"" |
"" |
"" |
10px |
10px |
10px |
"" |
| Assert default/initial value for background-position-y is 1em |
"" |
"" |
"" |
13px |
13px |
13px |
"" |
| Assert default/initial value for backgroundPositionY is 1em |
"" |
"" |
"" |
13px |
13px |
13px |
"" |
3. jQuery('#bp').css('background-position', '10px 5%')
| Assertion |
Firefox |
Internet Explorer |
Safari |
Opera |
| 1.5.0.12 |
2.0.0.18 |
3.0.4 |
6.0 |
7.0 |
3.2 |
9.62 |
| Assert set value for background-position is 10px 5% |
"" |
"" |
10px 5% |
undefined |
undefined |
10px 5% |
10px 0px |
| Assert set value for backgroundPosition is 10px 5% |
10px 5% |
10px 5% |
10px 5% |
10px 5% |
10px 5% |
10px 5% |
10px 5% |
| Assert set value value for background-position-x is 10px |
"" |
"" |
"" |
10px |
10px |
10px |
"" |
| Assert set value value for backgroundPositionX is 10px |
"" |
"" |
"" |
10px |
10px |
10px |
"" |
| Assert set value value for background-position-y is 5% |
"" |
"" |
"" |
55px |
55px |
5% |
"" |
| Assert set value value for backgroundPositionY is 5% |
"" |
"" |
"" |
5% |
5% |
5% |
"" |
4. jQuery('#bp').css('backgroundPosition', '10px 5%')
| Assertion |
Firefox |
Internet Explorer |
Safari |
Opera |
| 1.5.0.12 |
2.0.0.18 |
3.0.4 |
6.0 |
7.0 |
3.2 |
9.62 |
| Assert set value for background-position is 10px 5% |
"" |
"" |
10px 5% |
undefined |
undefined |
10px 5% |
10px 0px |
| Assert set value for backgroundPosition is 10px 5% |
10px 5% |
10px 5% |
10px 5% |
10px 5% |
10px 5% |
10px 5% |
10px 5% |
| Assert set value value for background-position-x is 10px |
"" |
"" |
"" |
10px |
10px |
10px |
"" |
| Assert set value value for backgroundPositionX is 10px |
"" |
"" |
"" |
10px |
10px |
10px |
"" |
| Assert set value value for background-position-y is 5% |
"" |
"" |
"" |
55px |
55px |
5% |
"" |
| Assert set value value for backgroundPositionY is 5% |
"" |
"" |
"" |
5% |
5% |
5% |
"" |
5. jQuery('#bp').css({backgroundPosition: '10px 5%'})
| Assertion |
Firefox |
Internet Explorer |
Safari |
Opera |
| 1.5.0.12 |
2.0.0.18 |
3.0.4 |
6.0 |
7.0 |
3.2 |
9.62 |
| Assert set value for background-position is 10px 5% |
"" |
"" |
10px 5% |
undefined |
undefined |
10px 5% |
10px 0px |
| Assert set value for backgroundPosition is 10px 5% |
10px 5% |
10px 5% |
10px 5% |
10px 5% |
10px 5% |
10px 5% |
10px 5% |
| Assert set value value for background-position-x is 10px |
"" |
"" |
"" |
10px |
10px |
10px |
"" |
| Assert set value value for backgroundPositionX is 10px |
"" |
"" |
"" |
10px |
10px |
10px |
"" |
| Assert set value value for background-position-y is 5% |
"" |
"" |
"" |
55px |
55px |
5% |
"" |
| Assert set value value for backgroundPositionY is 5% |
"" |
"" |
"" |
5% |
5% |
5% |
"" |
6. jQuery('#bp').css('background-position-x', '10px')
| Assertion |
Firefox |
Internet Explorer |
Safari |
Opera |
| 1.5.0.12 |
2.0.0.18 |
3.0.4 |
6.0 |
7.0 |
3.2 |
9.62 |
| Assert set value for background-position is 10px 0% |
"" |
"" |
0% 0% |
undefined |
undefined |
10px |
0px 0px |
| Assert set value for backgroundPosition is 10px 0% |
"" |
"" |
0% 0% |
10px_ |
10px_ |
10px |
0px 0px |
| Assert set value value for background-position-x is 10px |
"" |
"" |
"" |
10px |
10px |
10px |
"" |
| Assert set value value for backgroundPositionX is 10px |
10px |
10px |
10px |
10px |
10px |
10px |
10px |
7. jQuery('#bp').css('background-position-y', '10px')
| Assertion |
Firefox |
Internet Explorer |
Safari |
Opera |
| 1.5.0.12 |
2.0.0.18 |
3.0.4 |
6.0 |
7.0 |
3.2 |
9.62 |
| Assert set value for background-position is 0% 10px |
"" |
"" |
0% 0% |
undefined |
undefined |
10px |
0px 0px |
| Assert set value for backgroundPosition is 0% 10px |
"" |
"" |
0% 0% |
_10px |
_10px |
10px |
0px 0px |
| Assert set value value for background-position-y is 10px |
"" |
"" |
"" |
10px |
10px |
10px |
"" |
| Assert set value value for backgroundPositionY is 10px |
10px |
10px |
10px |
10px |
10px |
10px |
10px |
8. jQuery('#bp').css({backgroundPositionX: '10px', backgroundPositionY: '5%'})
| Assertion |
Firefox |
Internet Explorer |
Safari |
Opera |
| 1.5.0.12 |
2.0.0.18 |
3.0.4 |
6.0 |
7.0 |
3.2 |
9.62 |
| Assert set value for background-position is 10px 5% |
"" |
"" |
0% 0% |
undefined |
undefined |
10px 5% |
0px 0px |
| Assert set value for backgroundPosition is 10px 5% |
"" |
"" |
0% 0% |
10px 5% |
10px 5% |
10px 5% |
0px 0px |
| Assert set value value for background-position-x is 10px |
"" |
"" |
"" |
10px |
10px |
10px |
"" |
| Assert set value value for backgroundPositionX is 10px |
10px |
10px |
10px |
10px |
10px |
10px |
10px |
| Assert set value value for background-position-y is 5% |
"" |
"" |
"" |
55px |
55px |
5% |
"" |
| Assert set value value for backgroundPositionY is 5% |
5% |
5% |
5% |
5% |
5% |
5% |
5% |
9. jQuery('#bp').css({backgroundPositionX: 'right', backgroundPositionY: 'bottom'})
| Assertion |
Firefox |
Internet Explorer |
Safari |
Opera |
| 1.5.0.12 |
2.0.0.18 |
3.0.4 |
6.0 |
7.0 |
3.2 |
9.62 |
| Assert set value for background-position is 100% 100% |
"" |
"" |
0% 0% |
undefined |
undefined |
100% 100% |
0px 0px |
| Assert set value for backgroundPosition is 100% 100% |
"" |
"" |
0% 0% |
right bottom |
right bottom |
100% 100% |
0px 0px |
| Assert set value value for background-position-x is 100% |
"" |
"" |
"" |
right |
right |
100% |
"" |
| Assert set value value for backgroundPositionX is 100% |
right |
right |
right |
right |
right |
100% |
right |
| Assert set value value for background-position-y is 100% |
"" |
"" |
"" |
bottom |
bottom |
100% |
"" |
| Assert set value value for backgroundPositionY is 100% |
bottom |
bottom |
bottom |
bottom |
bottom |
100% |
bottom |
Interpreting the initial results
The main findings I took from this were:
- Often when the css syntax version of a property (e.g., background-position) failed the test, the camelCase version (e.g., backgroundPosition) passed
- When specified, keyword values and not percentages are reported (when recognised) by all browsers, except Safari (test 9)
- The CSS 2.1 initial values for an element of 0% 0% are not always returned in % (test 1)
- Setting the double axis property does not always guarantee that the single axis properties are set to match it
- Setting a single axis property (e.g., background-position-x) does not guarantee that the double axis property (e.g., background-position) is set to match it (tests 6, 7 and 8)
- Non-px length values are sometimes converted to px (see em conversion to px in test 2)
Step 2: Treating css syntax as camelCase