Tom Bennet

Pixels Please: Image Scaling in CSS

March 26, 2015

Until now, web developers have had very little control over how browsers render images when they’re scaled.

Take Mario, for instance:

Mario good pixelation

This is a 24x32 pixel image, scaled up using Photoshop to preserve its crisp, blocky composition. It’s a great example of the low-res pixel art that’s long been a staple of retro and indie games. Let’s see how our image is rendered in the browser when scaled up using CSS:

Mario bad pixelation

As you can see, the effect is suboptimal - the browser’s default scaling algorithm (usually bi-linear interpolation) has applied anti-aliasing to the image. Whilst good for the majority of purposes, this type of scaling sacrifices the detail in our pixel art. Is there a way to tell the browser to use nearest neighbour interpolation, as we used in Photoshop, to preserve the pixelation of our Mario?

The CSS Image Rendering Property

The image-rendering CSS property aims to do just this. The property can be applied to CSS background images, inline images, and canvas elements.

You can see the effect in the CodePen below. On the left, the image is rendered as per default behaviour, with the property value set to auto. On the right, we’ve applied our preferred scaling method:

Browser Support

As with all cutting-edge features, there is a degree of inconsistency between browsers. Firefox supports the crisp-edges value with the -moz prefix, in both desktop and mobile versions. Safari now supports the same value, but with the -webkit prefix, on both desktop and mobile. Opera, which is of course Chromium-based, supports the unprefixed value pixelated, much like the most recent version of Google Chrome.

Finally, whilst Internet Explorer does not support image-rendering, we can achieve the same effect by using a non-standard property that has been knocking around since IE 7. By applying -ms-interpolation-mode: nearest-neighbor to the image, our pixel art will remain pleasingly blocky.

The appropriate combination of properties and prefixes are provided below, including some non-standard legacy values supported in older browsers. I’ve also put them into a SCSS mixin for convenience, which is available here as a gist.

If the current browser support is a serious obstacle for you, there are workarounds and alternatives: you can manually resize and export at a higher resolution using your preferred graphics program, or you can upscale using canvas with the imageSmoothingEnabled property. But that’s a tutorial for another time.

I hope this short guide has been useful. Let me know your thoughts on Twitter - I’m @tomcbennet. You might also enjoy my feature on Command & Conquer, which prompted me to explore this technique.

Thanks for reading, and may all your pixel art stay gloriously blocky.

Credit: Mario pixel art by skyluigi

Return to Blog