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:

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:

  1. Often when the css syntax version of a property (e.g., background-position) failed the test, the camelCase version (e.g., backgroundPosition) passed
  2. When specified, keyword values and not percentages are reported (when recognised) by all browsers, except Safari (test 9)
  3. The CSS 2.1 initial values for an element of 0% 0% are not always returned in % (test 1)
  4. Setting the double axis property does not always guarantee that the single axis properties are set to match it
  5. 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)
  6. Non-px length values are sometimes converted to px (see em conversion to px in test 2)

Step 2: Treating css syntax as camelCase