Skip to content

Pixel ​

RGB pixel column backgrounds for any Tailwind color. LCD or CRT phosphor look, pure CSS.

Pixel mixes additively, the way a display emits light. Its sibling Comic dots mixes subtractively, the way ink lands on paper. Left at their defaults both read back as the color you passed in; turn the knobs up and the channels come apart.

Browser support

Built on CSS relative color syntax (rgb(from ... r 0 0)), registered custom properties and the tan() and atan2() trig functions. Live status for each is at the foot of this page.

Do not pair this with text-contrast-*

The columns sit on a black base, so the surface a reader sees is part phosphor and part black, in a proportion set by pixel-gap, pixel-size and pixel-bloom. text-contrast-* solves against one flat color and has no way to know any of that. Pick the text color by hand here. See Composition.

Quick reference ​

class styles
bg-pixel-<color>Sets color and applies RGB pixel pattern with background-blend-mode: screen
bg-pixel-<color>/<opacity>Same with opacity modifier, 0-100
bg-pixel-<color>/[<number>]Same with a 0-1 opacity
bg-pixel-[<value>]Arbitrary color value
bg-pixel-(--var)Color from a custom property
pixel-size-<number>--jib-pixel-size: --spacing(<number>) / 4. Pixel size; width = size, height = size × 2.
pixel-size-[<value>]--jib-pixel-size: <value>
pixel-gap-<number>--jib-pixel-gap: <number>. Gap as a multiple of pixel width.
pixel-gap-[<value>]--jib-pixel-gap: <value>
pixel-bloom-<number>--jib-pixel-bloom: --spacing(<number>) / 4. Phosphor bloom; unbounded, saturates to solid.
pixel-bloom-[<value>]--jib-pixel-bloom: <value>

How it works ​

The color splits into its RGB channels, the direct components of additive light:

ColumnColorExtraction
R (red)rgb(r 0 0)Red channel only
G (green)rgb(0 g 0)Green channel only
B (blue)rgb(0 0 b)Blue channel only

Four background layers composite together. Each channel needs its own layer for screen blending to add up:

  1. Row mask. repeating-linear-gradient(to bottom, ...) with white rows and black gaps, blended with multiply to punch out the horizontal row separators.
  2. Red column. repeating-linear-gradient(to right, ...) at column position 0, blended with screen.
  3. Green column. The same, at column position 1, blended with screen.
  4. Blue column. The same, at column position 2, blended with screen.

All of it over a black background-color. screen adds the channels back together, which is additive mixing, and what comes out is tall rectangular pixels in R|G|B triplets, much like a real LCD panel.

Raise pixel-bloom above 0 and each column widens until neighbors overlap into secondary colors: yellow, cyan, magenta. That overlap is the CRT phosphor glow.

bg-blend-* overwrites that list

background-blend-mode repeats a single value across every layer, and Tailwind's bg-blend-* sets one. It sorts after the texture, so bg-pixel-* bg-blend-screen flattens the row mask's multiply and the columns' screen into one mode, and the additive mix stops adding up.

Basic usage ​

Add bg-pixel-<color> to any element:

Gap ​

Control the space between each R|G|B pixel triplet with pixel-gap-<number>. The value multiplies the pixel width, so pixel-gap-1 is 1x and pixel-gap-2 is 2x. The default is 1.

gap-0.5

gap-1

gap-1.5

gap-2

gap-4

Gap scales with pixel size, so changing pixel-size-* moves the gap along with it.

Size ​

Control the pixel size with pixel-size-<number>. Scales at spacing/4 so pixel-size-1 = 1px, pixel-size-2 = 2px. Width equals the size value and height is twice that, so a pixel keeps a 1:2 ratio. The default is 1px.

size-1

size-2

size-3

size-4

size-6

Bloom ​

Control the phosphor bloom with pixel-bloom-<number>. Scales at spacing/4 so pixel-bloom-1 = 1px. This widens each channel outward so adjacent columns overlap additively, which is the CRT glow. The dial is unbounded; at high values every channel saturates and the pixel structure dissolves into solid color. The default is 1px.

  • pixel-bloom-0 gives crisp hard-edged rectangles, the LCD look
  • pixel-bloom-1 gives a slight glow, and is the default
  • pixel-bloom-2 makes adjacent channels meet
  • Larger values saturate, and the structure fades into flat color

bloom-0

bloom-1

bloom-2

bloom-3

bloom-4

Opacity ​

Add an opacity modifier with the / syntax to fade the whole pattern: all three RGB channel layers, the row mask and the black background. The bare value is a percentage (0–100); a bracketed value is a 0–1 alpha, so /50 and /[0.5] are the same. The bracketed-percentage form /[50%] that the color utilities accept is not available here, because converting it would need calc(x / 100%), which Firefox rejects.

100%

/75

/50

/25

/10

It scales every RGB channel opacity by the same factor and turns the black background semi-transparent, so you can layer the pattern over whatever is underneath.

over gradient

over gradient

RGB channel behavior ​

Every Tailwind color at every shade, rendered as pixels. Whites light all three R|G|B columns equally. Pure hues light only the channels they need: red lights R, blue lights B, yellow lights R+G.

Slate

Gray

Red

Orange

Amber

Yellow

Green

Emerald

Cyan

Blue

Violet

Purple

Fuchsia

Pink

Rose

Using a custom value ​

Use the arbitrary value syntax for colors not in the Tailwind palette:

Applying conditionally ​

All bg-pixel-* and pixel-* utilities support Tailwind's variant syntax:

html
<!-- sub-pixels on hover -->
<div class="bg-blue-500 hover:bg-pixel-blue-500"></div>

<!-- larger pixels from md up -->
<div class="bg-pixel-red-500 md:pixel-size-3"></div>

In practice ​

At page scale the same utilities read as surfaces rather than swatches: chrome, hero and cards are one bg-pixel-* class each over a shared black backplate. Small elements carry pixel-bloom-2 so the columns merge instead of chewing through the glyphs, and text color is picked by hand for the reason in the callout above.

pixel · console ui

RASTERlive
bg-pixel-blue-900
Every color is three columns of light.
fuchsia · 700R+B
yellow · 500R+G
cyan · 700G+B
flat input · no texturesubmit →

Import ​

Included in @import 'tw-jib-css'. To import individually:

css
@import 'tw-jib-css/pixel';

Baseline status

What these utilities are built on, live from the Web Platform Dashboard.