Making pixel art survive a 4K screen
Pixel art on the web has one job: not be blurry. Everything else: the palette, the dithering, the chunky borders, is decoration on top of that. Get the rendering wrong and the whole aesthetic collapses into "slightly out of focus".
These are the rules this site is built on, in rough order of how much they matter.
1. Never let the browser resample your art
The default scaling algorithm is smooth, which is correct for photographs and fatal for pixel art. One property fixes it:
img.pixel-art {
image-rendering: pixelated;
}
Every raster image with intentional pixels, icons, sprites, favicons rendered as images, needs it. Anywhere it is missing, that image is being interpolated.
2. Scale by whole numbers
A 16-pixel sprite at 1.5× produces pixels that are alternately one and two screen pixels wide. No rendering setting fixes that; the grid itself is broken. Either pick integer multiples, or accept that the browser will round and keep the source small enough that the rounding is invisible.
3. Pixel fonts have a size they want to be
Bitmap-style fonts are designed on a grid. At their intended size they are perfect. At any other size, the browser interpolates and they turn to mush.
Two habits that prevent most of it:
- Use them at small, deliberate sizes. This site uses a pixel face for headings and labels only, at sizes that suit it.
- Turn off smoothing on text that must render crisply:
-webkit-font-smoothing: noneon the elements using it.
And critically: do not use a pixel font for body copy. It is exhausting to read at paragraph length and it fails on small screens. Pair it with a clean sans for anything longer than a label, that contrast is also what makes the pixel parts feel deliberate rather than sloppy.
4. Borders should be real pixels, not drawn curves
If a border is meant to look pixelated, do not draw it with a rounded rectangle and
hope. Either use box-shadow chains that land on whole pixels, an SVG with
shape-rendering: crispEdges, or actual repeated elements.
.pixel-frame {
border: 3px solid #dfe9ff; /* a whole number of px */
box-shadow: 0 0 0 3px #03050c;
image-rendering: pixelated;
}
5. Let the canvas be a canvas
Animated pixel backgrounds, the fire on this site is one, should render at their native resolution and be scaled up by CSS, not drawn at the display resolution. Drawing at device resolution and then downsampling is what produces that soft, slightly glowing look that reads as "retro but wrong".
Also set image-rendering: pixelated on the canvas element itself, or the
CSS scaling reintroduces exactly the smoothing you avoided in the drawing code.
6. Respect the motion and contrast basics anyway
A pixel aesthetic is not a licence to abandon accessibility. Two things that get forgotten:
- Contrast. Dark backgrounds with dim grey text look moody on your monitor and are unreadable on a phone in daylight. Check the actual ratio.
- Reduced motion. Wrap every ambient animation in a
prefers-reduced-motioncheck. The fire is nice; it is not worth making someone nauseous.
@media (prefers-reduced-motion: reduce) {
.ambient-animation { animation: none; }
}
What it comes down to
Pixel art on the web is mostly a discipline about integers. Whole-pixel borders, whole number scaling, native-resolution rendering, fonts used at their intended size. Do those things and the aesthetic holds at any resolution. Skip one and that is exactly the part that looks wrong.
This site pairs a pixel face for headings with a modern sans for body text, and the result survives being scaled, screenshotted and squeezed into a phone. That combination is what I would recommend to anyone trying the same thing.