Thursday, October 01, 2009

A quick fix for the 1px rounding error

[Here's the quick solution if you can't be bothered to read this whole post: stick a border on the div that's causing the 1px rounding error].

Now let me elaborate, because there's actually a bit more to it than that...

We (like many other web design companies) generally design our websites as fixed-width, centered in the browser window, and optimised to 1024px wide with no horizontal scrolling at 1024. When you take the vertical scrollbar into account that means the maximum width for the outer container div is 1004px.

Sue likes to design websites with quite substantial dropshadows on either side of the outer container, which makes the whole graphic wider than 1004px. No problem - I just create the dropshadow as a single graphic which I style as a background image on the body tag in the CSS, centered in the browser window by setting the width of the graphic to 50% - like this:

body {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 62.5%;
text-align: center;
margin: 0;
padding: 0;
color: #595959;
background: #009ec7 url(../img/bg-page.jpg) no-repeat 50% 0;
}

#container {
width: 960px;
margin: 0 auto 0 auto;
padding: 0 0 10px 0;
text-align: left;
background-color: #fff;
}

The example above is for a site where the shadow starts off fairly narrow at the top, gets a lot fatter for a couple of hundred pixels, then gradually gets narrower again until it disappears altogether. It makes the page look like it's rising off the background for a while near the top of the browser window.

Here's the shadow graphic (click to enlarge):



With a design where the shadow is a consistent width all the way down the page, you would take a narrow strip of shadow and save that as a vertically-tiled background image instead - and the CSS would look like this:

background: #009ec7 url(../img/bg-page.jpg) repeat-y 50% 0;

The problem with this solution (whether you use a single or a tiled background image) is the mixing of the fixed-width #container div together with a percentage-positioned background graphic. Exact pixel widths don't play well with percentages in CSS, and the combination of the two is likely to create a 1px rounding error in many situations. It's why we generally stick to one or the other and don't use both together unless we absolutely have to.

In my example, this is what you get when you view the site in Opera or Safari on my Mac (click to enlarge image).

This is a screenshot of the right-hand side of the page within the browser window. You can clearly see a 1px-wide white "border" to the right of the light blue header, and you can also see a distinct "step" further down the page, which marks the bottom of the dropshadow background image on the body tag.

Interestingly enough, the 1px rounding error on this site only showed up in Safari on my Mac and Opera on Mac and PC. Firefox was fine (of course) and amazingly enough, IE6 and IE7 on my test PC also handled it just fine - not a rounding error in sight!

But that's not good enough. My sites get tested in IE6, IE7, IE8, Firefox, Opera and Safari (at a minimum), and if it's not perfect in all browsers on all platforms I'm going to do my damnedest to try and fix it.

The 1px rounding error is one of the few bugs that gurus such as Holly and Big John at Position is Everything have reluctantly assigned to the "annoying bugs that can't be fixed" basket, but because I initially didn't recognise my bug as a 1px rounding error, I tried to fix it myself.

...and found a workaround for this particular example that works pretty well...

Read the full post