Subpixel Rendering

You know the problem. No matter what you do you can’t get two elements to line up properly. The connecting points are always off by one pixel.

Everyone doing Web development at some point or other comes across a layout problem where no matter what you do, you can’t get two elements to align perfectly. One or the other is always off by one pixel. I was pulling my hair out try to get the pointers on the back and next buttons to align perfectly. They just didn’t look perfect. Worse still, when I used the browser’s “Zoom In” command from the view menu, I could clearly see that the lines did not connect properly.

After hours of fiddling with element sizes and positioning, I was on the verge of giving up. It was then that I remembered similar layout problems that I dealt with when doing Silverlight development. Silverlight is Microsoft’s vector-based, Flash killer/non-killer plugin for creating RIAs. For whatever reason, versiond before 4.0 had terrible problems with exact positioning of elements, causing frequent one pixel disconnects when rendered to screen. The only way to resolve this was to use subpixel rendering. This was accomplished by positioning an element by using partial pixel values, such as 1.5 or 1.25. This would force Silverlight to output the element with subpixel rendering, eliminating the visual disconnect.

OK, so what the heck is subpixel rendering? You experience it everyday with the browser’s font smoothing. You know it as anti-aliasing. The browser looks at the bézier curves of the font and when it sees that a line passes though a pixel, it looks at how much of the pixel is intersected. Depending on the percentage, the browser outputs a percentage of the font’s color. Less means the pixel gets less of the font’s color. For the human eye this creates the illusion of smoother curves.

You can use this same technique to trigger subpixel rendering on an element by giving it percentage-based position, or percentage-based dimensions. Here are some examples:

.button {
    position: absolute;
    left: 0px;
    top: 2.5px;
    height: 23.5px;
    width: 23.5px;

Here’s a image of my next button with the browser zoomed in. As you can see the pointer doesn’t line up perfectly with the rest of the button. This caused a slightly noticeable disconnect at normal size as well.

next button with its pointer misaligned

Now here’s the same button with the pointer using position set to top: 2.5px;:

next button using subpixel positioning

Subpixel rendering solved the connect problem I had at all zoom levels, including at normal size. Depending on your problem, subpixel positioning may be enough, or subpixel dimensions may be enough, or you may need to do both. Using subpixel values can help resolve problems when your layouts are not coming out pixel perfect.

You can try this out online or download the source code.

Today’s new technology terms:

   A pixel rendered with a shade of an adjacent element’s color to make it appear as if the element occupies part of that pixel’s space.
   To force the browser to render an element with subpixel values.
   The act of forcing an element to render with subpixel values or the condition of being rendered with subpixel values.