Pixel Perfect Sprites for the Modern Page
Back in the day, putting up sprites on your site was easy. Today, things are a little more complicated. What may look like a crisp sprite to you looks blurry or distorted on other displays. When zooming enters the picture, things get even more complicated. This page walks you through the issues with displaying sprites across monitors and the solutions available to you.
This all began when I noticed that my link button looked a little blurry. No matter whether I uploaded it to Imgur or Neocities, I couldn't get it to stop looking blurry. I was frustrated by this because I'd drawn it by hand and wanted to preserve that crisp look. Some research led me to what I thought was the culprit - the image-rendering algorithm. By default, this is set to 'auto', which uses antialiasing when zooming. Apparently even when not zooming. The solution seemed to be using the 'pixelated' option instead. Problem solved, right?
When I noticed the blurry sprite thing happening at the Cave of Dragonflies, I sent an email to the owner about it. She told me she had already tried using the 'pixelated' option, but there was a problem - it looked really bad on her monitor. She had 125% display scaling, and apparently 'pixelated' does not play nice with that. What was more curious to me was that she said that the 'auto' option did not blur the sprites for her. What was going on?
Apparently, the issue had to do with the monitor I was using. When I tested sprites with default image-rendering using my Macbook or my iPad, I got that fuzz on the edges. When I used my Thinkpad or HP monitor, though, they looked normal. And the 125% scaling caused the 'pixelated' option to look pretty ugly.
JS Option
I really wanted to have nice, crisp edges on my sprites, even when viewing on my Macbook. At the same time, I couldn't ignore that the solution of using 'pixelated' would look ugly to anyone using display scaling or zooming in. Some Googling found a potential solution: greggman's pixel-perfect.js. By forcing pixels to only scale by a whole number, you could keep them pixelated at larger sizes and preserve their shape. Nice!
I did some testing on my monitors and noted the results, which you can see below. The "pixel-perfect" option performed the best with one exception - using a gesture on the trackpad to pinch to zoom caused some slight distortion because it did not trigger the Javascript to keep the sprite fixed. The distortion went away the more you zoomed in, and it did not affect browser zoom (using shortcuts like command + shift + plus).
This wasn't a perfect solution (and it required a lot of overhead - you needed the size of each sprite added as a style), but it was pretty good. I wanted to share it with you all in case you ran into the same problem and really wanted to keep sprites looking pixelly for as many different monitors as possible and at different levels of zoom.
CSS-only Option
If you want a simpler, CSS-only solution, you could use a media query to check if the monitor has a device pixel ratio of 2 or more, since that seems to be what causes blurriness at 100% zoom. If so, you could apply the 'pixelated' property in just that case. Do note however that it means the zoom will look weird.
@media (min-resolution: 2dppx) {
img.sprite {
image-rendering: pixelated;
}
}
Testing Results
Below you can see for yourself what the different solutions look like on your screen, and the results of my testing.
Your DPR is: {{ dpr }}, {{ retinalike }}No image rendering applied: ![]()
Image rendering applied pixelated: ![]()
Image rendering applied crisp edges: ![]()
"Pixel perfect" guy: ![]()
HP Monitor (DPR 1)
| Scenario | Auto | Pixelated | Crisp edges | Pixel perfect |
|---|---|---|---|---|
| 100% | fine | fine | fine | fine |
| Browser zoom (110–125%) | blurry | distorted | blurry | fine |
| Gesture zoom | blurry | distorted | blurry | distorted |
ThinkPad (DPR 1.25), display scaling 100%
| Scenario | Auto | Pixelated | Crisp edges | Pixel perfect |
|---|---|---|---|---|
| Browser 100% | fine | fine | fine | fine |
| Browser zoom (110–125%) | blurry | distorted | fine | fine |
| Gesture zoom | blurry | distorted | distorted | distorted |
ThinkPad (DPR 1.25), display scaling 125%
| Scenario | Auto | Pixelated | Crisp edges | Pixel perfect |
|---|---|---|---|---|
| Browser 100% | blurry | distorted | distorted | fine |
| Browser zoom (110–125%) | blurry | distorted | distorted | fine |
| Gesture zoom | blurry | distorted | distorted | distorted |
Liquid Retina (DPR 2)
| Scenario | Auto | Pixelated | Crisp edges | Pixel perfect |
|---|---|---|---|---|
| 100% | blurry | fine | blurry | fine |
| Browser zoom (110–125%) | blurry | distorted | blurry | fine |
| Gesture zoom | blurry | distorted | blurry | distorted |