EmpireUI
Get Pro
← Blog8 min read#retro design#pixel art#css

Retro UI Design: Pixel Art, Scanlines and Old-School Nostalgia

Retro UI design brings pixel art, CRT scanlines, and 8-bit palettes back into modern interfaces. Here's how to build it properly with CSS and React.

Vintage CRT monitor glowing with pixel art game interface in the dark

Why Retro UI Is Having a Moment (Again)

It's 2026 and half the design community is racing toward glassmorphism and aurora gradients while the other half is dusting off pixel grids and CRT filters. That tension is exactly why retro UI feels so refreshing right now — it's the deliberate rejection of polish.

Honestly, a lot of modern UIs have converged into the same frosted glass, soft shadow, rounded corner soup. Retro design breaks that. Hard edges. Visible pixels. Scan lines that remind you screens used to be physical objects with physical limitations.

The aesthetic draws heavily from 1980s and early 1990s computing — think DOS prompts, early Macintosh UIs, arcade cabinets, and Game Boy screens. Worth noting: this isn't just nostalgia bait for people who grew up in that era. Younger designers are drawn to it precisely because they didn't live it. It's exotic to them.

If you want to see where retro design sits in the broader landscape of UI styles, browse the components — the contrast with styles like aurora or vaporwave makes the retro aesthetic's deliberate roughness immediately obvious.

The Core Visual Vocabulary of Retro UI

Retro UI isn't one thing. It's a cluster of overlapping aesthetics, each with its own rules.

Pixel art interfaces use a strict grid — typically 8px or 16px base units — and avoid anti-aliasing entirely. Every edge is crisp. Colors come from limited palettes: the original Game Boy used four shades of green-grey. The NES could display 54 colors total. That constraint is the point. When you artificially restrict your palette to 8 colors, every choice matters in a way that 16 million colors never forces you to think about.

CRT aesthetics are a different branch. Here you're simulating the physical properties of cathode-ray tube monitors: slight barrel distortion at the edges, horizontal scanlines every 2px, RGB phosphor glow, and a faint screen flicker. The colors are slightly over-saturated because CRT phosphors bloom. You can fake all of this in CSS. We'll get to the code in a minute.

Terminal/DOS aesthetics lean into monospace fonts, green or amber text on black, blinking cursors, and that very specific feeling of a machine waiting for your input. Think less 'video game' and more 'you've just hacked into a mainframe in a 1995 movie.'

Building Scanlines and CRT Effects in Pure CSS

The scanline effect is the single most recognizable CRT property and it's surprisingly cheap to implement. Two CSS techniques work well: a repeating linear gradient overlay, or a pseudo-element with a semi-transparent striped background.

Here's a self-contained component that wraps any content in a CRT frame:

// CRTWrapper.jsx
import React from 'react';

export function CRTWrapper({ children }) {
  return (
    <div className="crt-frame">
      <div className="crt-screen">
        {children}
      </div>
    </div>
  );
}
```

```css
/* crt.css */
.crt-frame {
  background: #1a1a1a;
  border-radius: 12px;
  padding: 24px;
  box-shadow:
    0 0 0 4px #333,
    0 0 40px rgba(0, 255, 100, 0.15);
}

.crt-screen {
  position: relative;
  overflow: hidden;
  background: #0a0f0a;
  color: #39ff14; /* classic phosphor green */
  font-family: 'Courier New', monospace;
  font-size: 14px;
  line-height: 1.6;
  padding: 16px;
}

/* Scanlines overlay */
.crt-screen::after {
  content: '';
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    to bottom,
    transparent 0px,
    transparent 2px,
    rgba(0, 0, 0, 0.15) 2px,
    rgba(0, 0, 0, 0.15) 4px
  );
  pointer-events: none;
  z-index: 10;
}

/* Optional flicker animation */
@keyframes flicker {
  0%, 100% { opacity: 1; }
  92% { opacity: 1; }
  93% { opacity: 0.97; }
  94% { opacity: 1; }
}

.crt-screen {
  animation: flicker 8s infinite;
}

That repeating-linear-gradient is doing the heavy lifting. The 4px cycle (2px transparent, 2px dark) matches the actual pixel density of most CRT displays from 1984-1998. You can adjust the dark stop's opacity — 0.15 is subtle enough not to destroy readability, but feel free to push to 0.3 for a more aggressive effect.

One more thing — the pointer-events: none on the pseudo-element is essential. Skip it and you'll spend an hour debugging why your buttons won't click.

Pixel Art Typography and Font Choices

Typography kills more retro designs than anything else. You can nail the scanlines and the color palette and then drop in a clean sans-serif and the whole thing collapses.

In practice, you want bitmap fonts or fonts designed to look like them. Press Start 2P from Google Fonts is the obvious choice — it's the go-to 8x8 pixel font that reads as 'retro game UI' instantly. VT323 works for terminal aesthetics. Silkscreen for a slightly more versatile pixel look. Load them at exactly the size they're designed for: Press Start 2P at 8px, 16px, or 32px — not 13px or 19px, because you'll get blurry scaling.

The CSS property you actually need here is image-rendering: pixelated when you're scaling any pixel art assets. By default, browsers apply bilinear interpolation when scaling images, which blurs the edges. Pixelated rendering keeps that crisp blocky look.

Quick aside: if you're using CSS transform: scale() on pixel art elements, pair it with image-rendering: pixelated and image-rendering: crisp-edges (the Firefox prefix). Both. Because browser support for this property in 2024 was still inconsistent enough that you want the fallback.

Color Palettes: Working Within Constraints

This is where retro design gets philosophically interesting. Why would you deliberately limit yourself to 8 or 16 colors when you have access to the full sRGB gamut?

Because constraint breeds creativity. Look at any well-executed pixel art and you'll see how much expressiveness comes from careful dithering — alternating pixels of two colors to simulate a third. That's not a workaround. That's a technique that produces results you can't get any other way.

The most iconic palettes from real hardware: the Game Boy's four shades of olive-grey (#0f380f, #306230, #8bac0f, #9bbc0f), the Commodore 64's 16-color set, the CGA palette's aggressive cyan-magenta-white combination that aged about as well as you'd expect. For modern retro work, the PICO-8 fantasy console palette (16 colors, introduced around 2015) has become almost a standard — it's carefully balanced and instantly recognizable.

That said, you don't have to cosplay specific hardware. A coherent 8-color palette you define yourself works fine. Pick a dominant dark background, one or two accent colors with high contrast, and a neutral mid-tone for secondary text. That's the whole system. If you're building something adjacent to cyberpunk rather than pure retro, Empire UI's cyberpunk components show how neon palettes can inherit some of the same high-contrast energy.

Retro UI in Component Libraries: What to Borrow and What to Skip

Not every retro technique belongs in a production UI. Let's be direct about what's worth keeping.

Scanlines: yes, as a subtle overlay on showcase or hero sections. Full-screen scanlines on a dashboard that users stare at for eight hours? No. Eye strain is real. Keep the aesthetic to framing elements, not the actual content canvas.

Pixel fonts: use them for headings, labels, and decorative text. Never for body copy longer than two sentences. Press Start 2P at 8px is charming for a score counter. It's genuinely painful for a 400-word product description.

The retro aesthetic pairs surprisingly well with neobrutalism — both embrace hard edges, visible borders, and rejection of the soft-everything trend. If you're building something that should feel bold and a bit aggressive, that combination is worth exploring. The box shadow generator is useful for getting neobrutalist offset shadows that complement pixelated elements without looking accidental.

One more thing — retro UI works best as a complete commitment, not a few token pixels sprinkled on a clean modern layout. Either the whole experience is 8-bit or none of it is. Half-measures read as a mistake rather than a style choice.

Accessibility in Retro Design: The Part Nobody Talks About

Here's the hard conversation. CRT scanlines reduce contrast. Pixel fonts at small sizes reduce readability. Flickering animations can trigger photosensitive conditions. Retro UI, done carelessly, is a genuine accessibility problem.

The flicker animation in the code above uses prefers-reduced-motion to disable it for users who've opted out of motion. You should absolutely respect that:

@media (prefers-reduced-motion: reduce) {
  .crt-screen {
    animation: none;
  }
}

For scanline overlays, keep the opacity under 20% and test your contrast ratios against the WCAG 2.1 AA standard (4.5:1 for normal text, 3:1 for large text). Phosphor green (#39ff14) on black (#0a0f0a) passes easily — that's a contrast ratio around 15:1. Amber on black is similarly strong. Where retro designs fail is when designers use mid-range colors from the palette for text because 'it looks cool.' It might. But if your contrast ratio is 2.8:1, you've broken it for a lot of people.

Honestly, pixel fonts are the real accessibility landmine here. Test them with real users, not just design tool previews. At 8px on a 4K display, they might look fine in Figma and be unreadable on an actual screen.

FAQ

What's the difference between pixel art UI and retro UI?

Pixel art is a specific technique — drawing at a low resolution with a limited palette, then scaling up. Retro UI is broader: it includes CRT aesthetics, terminal looks, and early OS interfaces that don't necessarily use pixel art at all.

Can I use retro UI styles in a production app?

Yes, but selectively. Scanlines and pixel fonts work well for hero sections, games, or specialty tools. For dashboard-heavy apps, restrict the aesthetic to chrome and decoration — not the data-dense parts users read constantly.

Which CSS properties are most important for a CRT effect?

The repeating-linear-gradient pseudo-element for scanlines, plus a subtle text-shadow or filter: blur(0.3px) for phosphor glow. Add image-rendering: pixelated for any scaled pixel art assets.

Are there React component libraries for retro UI?

A few exist, but they're niche. You're usually better off building small, composable primitives yourself — a CRTWrapper component and a pixel-font text component covers 80% of use cases and keeps your bundle small.

Free components in 40 styles
React & Tailwind, copy-paste ready.
Browse →

Read next

Retro Pixel Art in CSS: Pixel Fonts, Sprite Animations, 8-bit UIY2K UI Design: Why the Year 2000 Aesthetic Is Back and BiggerCSS Loading Spinners: 12 Variants From Dots to Rings to BarsCSS Hover Effects Gallery: 10 Patterns Beyond color and opacity