UPDATE: test this out for yourself here. UPDATE 2: In IE9 the translate method does put the image at the half pixel.

Take a look at the following CSS

#element { left: 100.5px; }

Notice the half pixel? It will get rounded up to 1, resulting in the visible equivalent of:

#element { left: 101px; }

But what if we’re playing with hardware-accelerated CSS? When using CSS rules that are being handled by the GPU such as translate3d, an attempt will be made to put that element on the half pixel we defined, resulting in…? A blurry image. Take a look:

In this example we’ll be using the following Chrome Web Store image including the text underneath:

We’re putting 3 of those next to eachother.

First, the image as is. Second, the image translated half a pixel to the right and half a pixel down using the CSS rule transform: translate(.5px, .5px); Finally we're doing the same as in 2, this time using the CSS rule transform: translate3d(.5px, .5px, 0);

Tested on Windows, here are the results:

Chrome 20

As you can see, the translate method gets rounded to the equivalent of 1 pixel right and 1 pixel down. The image and text are placed a pixel lower than the original, but both text and image are crisp as the original.

The translate3d method blends the image and text to make it appear as if it is placed vertically between image 1 and 2. Notice the blurry text?

Firefox 14

Firefox seems to round the results in either translate and translate3d.

Safari 5.1.7

Safari obeys the given half pixel positioning in both translate and trandlate3d versions.

Opera 12

Opera doesn’t support translate or translate3d so the 2nd and 3rd element are not affected in their positioning at all.

Internet Explorer 9

IE9 shows that translate does put the image at the interpolated half as expected, and the translate3d is ignored.

Why is this important?

When moving an element around the screen, GPU-enabled transitions will result in a much smoother animation. But mind the end-state! If you don’t put the image on an exact pixel the end-result may remain blurry on the screen for some of your users.

I encountered this in real life as we’re creating a web-based book viewer at Q42 which allows the user to zoom and swipe the pages of a virtual book to any position the user wants. We are using translate3d for certain browsers to make the transitions smoother, but as we didn’t round the final pixel state, the end-result was blurry.

So this post is intended to make you aware of this potential situation: beware of half pixels in CSS!

Give it a try.

Final thoughts

The “half” pixel value .5 was taken as an example. Any floating value that puts the image between actual pixels on your display will have the GPU interpolate the colors to make it visually appear as if the image was positioned at the location provided: between the on-screen pixels.

To stress out the possible results of these actions I used the values that cause the most blurry effect: half a pixel horizontally and half a pixel vertically.

Also note that this applies to other metrics such as em and % as well; as long as the end result positions the element between on-screen pixels and when translate or translate3d is used (or any other GPU-accelerated CSS rule), the results shown above for each browser will apply.