03 / 20
All 20 in 20 Tailwind Retro UI
- 01Tailwind CRT Scanlines and Screen Curvature
- 02Tailwind Pixel Art Scaling with Image Rendering
- 03Tailwind Dithering Patterns with Gradients
- 04Tailwind One Bit Bevel Borders with Box Shadow
- 05Tailwind Classic Mac System 7 Window Chrome
- 06Tailwind MS DOS Text Mode Interface Grid
- 07Tailwind Teletext and Ceefax Block Graphics
- 08Tailwind Amber and Green Phosphor Monitor
- 09Tailwind Windows 95 Desktop Interface
- 10Tailwind Retro Futuristic Terminal Interface
- 11Tailwind Eight Bit Pixel Art Buttons and HUD
- 12Tailwind Neo Brutalist Component Board
- 13Tailwind Skeuomorphic Cassette Player
- 14Tailwind Vaporwave Aesthetic Scene
- 15Tailwind Retro Arcade Game Interface
- 16Tailwind ASCII Art Terminal Interface
- 17Tailwind Nineties Web Guestbook Widget
- 18Tailwind Y2K Aqua Gloss Interface Kit
- 19Tailwind Vintage Storefront Layout
- 20Tailwind Retro Desktop Portfolio Template
Tailwind Dithering Patterns with Gradients
Ordered dithering is how a limited palette fakes colours it does not have: alternate two available colours in a fixed pattern and the eye averages them. Built from layered repeating-conic-gradient checkerboards over flat palette fills — and because every pattern is an arbitrary background utility, each band's coverage is legible in the markup instead of hidden behind a modifier class.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="twr-03 relative block w-full min-h-svh box-border bg-twr03-bg text-twr03-ink font-twr03-cond" aria-labelledby="twr-03-title">
<h2 class="absolute size-px overflow-hidden [clip-path:inset(50%)] whitespace-nowrap" id="twr-03-title">Ordered dithering ramps built from gradients</h2>
<div class="absolute top-4 right-4 z-6">
<input class="peer absolute inset-0 size-11 m-0 opacity-0 cursor-pointer" type="checkbox" id="twr-03-theme">
<label class="grid place-items-center size-11 rounded-full border border-twr03-line bg-twr03-surface text-twr03-ink2 cursor-pointer peer-focus-visible:outline-2 peer-focus-visible:outline-twr03-acc peer-focus-visible:outline-offset-2" for="twr-03-theme">
<svg class="size-5" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12 4a8 8 0 0 0 0 16Z" fill="currentColor"/></svg>
<span class="absolute size-px overflow-hidden [clip-path:inset(50%)] whitespace-nowrap">Toggle dark surround</span>
</label>
</div>
<div class="grid grid-cols-[minmax(0,1fr)] gap-[clamp(1.5rem,1rem+2vw,2.25rem)] max-w-[68rem] mx-auto px-[clamp(0.85rem,0.5rem+2vw,2rem)] pt-[clamp(3.5rem,3rem+3vw,5rem)] pb-16">
<header class="grid gap-1.5 min-w-0">
<p class="m-0 font-twr03-mono text-[0.68rem] tracking-[0.14em] uppercase text-twr03-ink2">Palette · Game Boy DMG-01 · 4 tones, exact sRGB</p>
<h3 class="m-0 min-w-0 text-[clamp(1.35rem,1rem+2vw,2.2rem)] font-bold leading-[1.08] tracking-[-0.03em] text-balance">Four colours, twelve apparent tones</h3>
<p class="m-0 min-w-0 max-w-[52ch] text-[0.95rem] leading-relaxed text-pretty text-twr03-ink2">Every band below contains only palette colours. The intermediate tones are patterns, not blends.</p>
</header>
<div class="flex flex-wrap gap-2">
<span class="flex-none min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.03em] px-2.5 py-2 border border-twr03-line bg-twr03-p0 text-twr03-p3">#0f380f</span>
<span class="flex-none min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.03em] px-2.5 py-2 border border-twr03-line bg-twr03-p1 text-[#dff0a8]">#306230</span>
<span class="flex-none min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.03em] px-2.5 py-2 border border-twr03-line bg-twr03-p2 text-[#10290a]">#8bac0f</span>
<span class="flex-none min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.03em] px-2.5 py-2 border border-twr03-line bg-twr03-p3 text-[#10290a]">#9bbc0f</span>
</div>
<div class="grid grid-cols-[minmax(0,1fr)] gap-4 lg:grid-cols-2">
<article class="min-w-0 grid content-start gap-2.5 border border-twr03-line bg-twr03-surface p-[clamp(0.8rem,0.6rem+0.8vw,1.1rem)]" aria-labelledby="twr-03-r0">
<h4 class="m-0 min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.1em] uppercase text-twr03-ink2" id="twr-03-r0">Reference · unlimited colour</h4>
<div class="flex min-w-0 h-[clamp(64px,8vw,92px)] overflow-hidden border-2 border-[#0f380f] [background:linear-gradient(90deg,#0f380f,#306230,#8bac0f,#9bbc0f)]" aria-hidden="true"></div>
<p class="m-0 min-w-0 text-[0.82rem] leading-normal text-pretty text-twr03-ink2">A plain linear gradient. Contains thousands of colours the hardware never had.</p>
</article>
<article class="min-w-0 grid content-start gap-2.5 border border-twr03-line bg-twr03-surface p-[clamp(0.8rem,0.6rem+0.8vw,1.1rem)]" aria-labelledby="twr-03-r1">
<h4 class="m-0 min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.1em] uppercase text-twr03-ink2" id="twr-03-r1">2 colours · 2×2 Bayer</h4>
<div class="flex min-w-0 h-[clamp(64px,8vw,92px)] overflow-hidden border-2 border-[#0f380f]" aria-hidden="true">
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p0"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p0 [background-image:repeating-conic-gradient(var(--color-twr03-p3)_0%_25%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p0 [background-image:repeating-conic-gradient(var(--color-twr03-p3)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p3)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p3 [background-image:repeating-conic-gradient(var(--color-twr03-p0)_0%_25%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p3"></span>
</div>
<p class="m-0 min-w-0 text-[0.82rem] leading-normal text-pretty text-twr03-ink2">Darkest and lightest tone only. Five apparent steps from two real ones.</p>
</article>
<article class="min-w-0 grid content-start gap-2.5 border border-twr03-line bg-twr03-surface p-[clamp(0.8rem,0.6rem+0.8vw,1.1rem)]" aria-labelledby="twr-03-r2">
<h4 class="m-0 min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.1em] uppercase text-twr03-ink2" id="twr-03-r2">4 colours · adjacent-pair dither</h4>
<div class="flex min-w-0 h-[clamp(64px,8vw,92px)] overflow-hidden border-2 border-[#0f380f]" aria-hidden="true">
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p0"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p0 [background-image:repeating-conic-gradient(var(--color-twr03-p1)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p1)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p1"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p1 [background-image:repeating-conic-gradient(var(--color-twr03-p2)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p2)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p2"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p2 [background-image:repeating-conic-gradient(var(--color-twr03-p3)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p3)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p3"></span>
</div>
<p class="m-0 min-w-0 text-[0.82rem] leading-normal text-pretty text-twr03-ink2">Each pattern mixes only its two neighbouring palette entries.</p>
</article>
<article class="min-w-0 grid content-start gap-2.5 border border-twr03-line bg-twr03-surface p-[clamp(0.8rem,0.6rem+0.8vw,1.1rem)]" aria-labelledby="twr-03-r3">
<h4 class="m-0 min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.1em] uppercase text-twr03-ink2" id="twr-03-r3">8 steps · 2px cell, fine mask</h4>
<div class="flex min-w-0 h-[clamp(64px,8vw,92px)] overflow-hidden border-2 border-[#0f380f] [--twr-03-cell:2px]" aria-hidden="true">
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p0"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p0 [background-image:repeating-conic-gradient(var(--color-twr03-p1)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p1)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p1"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p1 [background-image:repeating-conic-gradient(var(--color-twr03-p2)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p2)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p2"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p2 [background-image:repeating-conic-gradient(var(--color-twr03-p3)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p3)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p3"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p3"></span>
</div>
<p class="m-0 min-w-0 text-[0.82rem] leading-normal text-pretty text-twr03-ink2">Same construction at a 2px cell. Closer to a blend, further from a period-correct look.</p>
</article>
</div>
<aside class="min-w-0 grid gap-2.5 border border-twr03-line border-l-4 border-l-twr03-acc bg-twr03-surface p-[clamp(0.85rem,0.6rem+1vw,1.2rem)]">
<h4 class="m-0 font-twr03-mono text-[0.7rem] tracking-[0.12em] uppercase text-twr03-ink2">Coverage table</h4>
<dl class="m-0 grid gap-1 text-[0.85rem]">
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">0%</dt><dd class="m-0 min-w-0 text-twr03-ink2">flat base colour, no overlay</dd></div>
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">25%</dt><dd class="m-0 min-w-0 text-twr03-ink2">one quadrant of the 2×2 cell</dd></div>
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">50%</dt><dd class="m-0 min-w-0 text-twr03-ink2">two opposite quadrants — checkerboard</dd></div>
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">75%</dt><dd class="m-0 min-w-0 text-twr03-ink2">three quadrants, inverse of 25%</dd></div>
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">100%</dt><dd class="m-0 min-w-0 text-twr03-ink2">flat next palette colour</dd></div>
</dl>
</aside>
</div>
</section><section class="twr-03 relative block w-full min-h-svh box-border bg-twr03-bg text-twr03-ink font-twr03-cond" aria-labelledby="twr-03-title">
<h2 class="absolute size-px overflow-hidden [clip-path:inset(50%)] whitespace-nowrap" id="twr-03-title">Ordered dithering ramps built from gradients</h2>
<div class="absolute top-4 right-4 z-6">
<input class="peer absolute inset-0 size-11 m-0 opacity-0 cursor-pointer" type="checkbox" id="twr-03-theme">
<label class="grid place-items-center size-11 rounded-full border border-twr03-line bg-twr03-surface text-twr03-ink2 cursor-pointer peer-focus-visible:outline-2 peer-focus-visible:outline-twr03-acc peer-focus-visible:outline-offset-2" for="twr-03-theme">
<svg class="size-5" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12 4a8 8 0 0 0 0 16Z" fill="currentColor"/></svg>
<span class="absolute size-px overflow-hidden [clip-path:inset(50%)] whitespace-nowrap">Toggle dark surround</span>
</label>
</div>
<div class="grid grid-cols-[minmax(0,1fr)] gap-[clamp(1.5rem,1rem+2vw,2.25rem)] max-w-[68rem] mx-auto px-[clamp(0.85rem,0.5rem+2vw,2rem)] pt-[clamp(3.5rem,3rem+3vw,5rem)] pb-16">
<header class="grid gap-1.5 min-w-0">
<p class="m-0 font-twr03-mono text-[0.68rem] tracking-[0.14em] uppercase text-twr03-ink2">Palette · Game Boy DMG-01 · 4 tones, exact sRGB</p>
<h3 class="m-0 min-w-0 text-[clamp(1.35rem,1rem+2vw,2.2rem)] font-bold leading-[1.08] tracking-[-0.03em] text-balance">Four colours, twelve apparent tones</h3>
<p class="m-0 min-w-0 max-w-[52ch] text-[0.95rem] leading-relaxed text-pretty text-twr03-ink2">Every band below contains only palette colours. The intermediate tones are patterns, not blends.</p>
</header>
<div class="flex flex-wrap gap-2">
<span class="flex-none min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.03em] px-2.5 py-2 border border-twr03-line bg-twr03-p0 text-twr03-p3">#0f380f</span>
<span class="flex-none min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.03em] px-2.5 py-2 border border-twr03-line bg-twr03-p1 text-[#dff0a8]">#306230</span>
<span class="flex-none min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.03em] px-2.5 py-2 border border-twr03-line bg-twr03-p2 text-[#10290a]">#8bac0f</span>
<span class="flex-none min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.03em] px-2.5 py-2 border border-twr03-line bg-twr03-p3 text-[#10290a]">#9bbc0f</span>
</div>
<div class="grid grid-cols-[minmax(0,1fr)] gap-4 lg:grid-cols-2">
<article class="min-w-0 grid content-start gap-2.5 border border-twr03-line bg-twr03-surface p-[clamp(0.8rem,0.6rem+0.8vw,1.1rem)]" aria-labelledby="twr-03-r0">
<h4 class="m-0 min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.1em] uppercase text-twr03-ink2" id="twr-03-r0">Reference · unlimited colour</h4>
<div class="flex min-w-0 h-[clamp(64px,8vw,92px)] overflow-hidden border-2 border-[#0f380f] [background:linear-gradient(90deg,#0f380f,#306230,#8bac0f,#9bbc0f)]" aria-hidden="true"></div>
<p class="m-0 min-w-0 text-[0.82rem] leading-normal text-pretty text-twr03-ink2">A plain linear gradient. Contains thousands of colours the hardware never had.</p>
</article>
<article class="min-w-0 grid content-start gap-2.5 border border-twr03-line bg-twr03-surface p-[clamp(0.8rem,0.6rem+0.8vw,1.1rem)]" aria-labelledby="twr-03-r1">
<h4 class="m-0 min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.1em] uppercase text-twr03-ink2" id="twr-03-r1">2 colours · 2×2 Bayer</h4>
<div class="flex min-w-0 h-[clamp(64px,8vw,92px)] overflow-hidden border-2 border-[#0f380f]" aria-hidden="true">
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p0"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p0 [background-image:repeating-conic-gradient(var(--color-twr03-p3)_0%_25%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p0 [background-image:repeating-conic-gradient(var(--color-twr03-p3)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p3)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p3 [background-image:repeating-conic-gradient(var(--color-twr03-p0)_0%_25%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p3"></span>
</div>
<p class="m-0 min-w-0 text-[0.82rem] leading-normal text-pretty text-twr03-ink2">Darkest and lightest tone only. Five apparent steps from two real ones.</p>
</article>
<article class="min-w-0 grid content-start gap-2.5 border border-twr03-line bg-twr03-surface p-[clamp(0.8rem,0.6rem+0.8vw,1.1rem)]" aria-labelledby="twr-03-r2">
<h4 class="m-0 min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.1em] uppercase text-twr03-ink2" id="twr-03-r2">4 colours · adjacent-pair dither</h4>
<div class="flex min-w-0 h-[clamp(64px,8vw,92px)] overflow-hidden border-2 border-[#0f380f]" aria-hidden="true">
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p0"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p0 [background-image:repeating-conic-gradient(var(--color-twr03-p1)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p1)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p1"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p1 [background-image:repeating-conic-gradient(var(--color-twr03-p2)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p2)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p2"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p2 [background-image:repeating-conic-gradient(var(--color-twr03-p3)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p3)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p3"></span>
</div>
<p class="m-0 min-w-0 text-[0.82rem] leading-normal text-pretty text-twr03-ink2">Each pattern mixes only its two neighbouring palette entries.</p>
</article>
<article class="min-w-0 grid content-start gap-2.5 border border-twr03-line bg-twr03-surface p-[clamp(0.8rem,0.6rem+0.8vw,1.1rem)]" aria-labelledby="twr-03-r3">
<h4 class="m-0 min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.1em] uppercase text-twr03-ink2" id="twr-03-r3">8 steps · 2px cell, fine mask</h4>
<div class="flex min-w-0 h-[clamp(64px,8vw,92px)] overflow-hidden border-2 border-[#0f380f] [--twr-03-cell:2px]" aria-hidden="true">
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p0"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p0 [background-image:repeating-conic-gradient(var(--color-twr03-p1)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p1)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p1"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p1 [background-image:repeating-conic-gradient(var(--color-twr03-p2)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p2)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p2"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p2 [background-image:repeating-conic-gradient(var(--color-twr03-p3)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p3)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p3"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p3"></span>
</div>
<p class="m-0 min-w-0 text-[0.82rem] leading-normal text-pretty text-twr03-ink2">Same construction at a 2px cell. Closer to a blend, further from a period-correct look.</p>
</article>
</div>
<aside class="min-w-0 grid gap-2.5 border border-twr03-line border-l-4 border-l-twr03-acc bg-twr03-surface p-[clamp(0.85rem,0.6rem+1vw,1.2rem)]">
<h4 class="m-0 font-twr03-mono text-[0.7rem] tracking-[0.12em] uppercase text-twr03-ink2">Coverage table</h4>
<dl class="m-0 grid gap-1 text-[0.85rem]">
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">0%</dt><dd class="m-0 min-w-0 text-twr03-ink2">flat base colour, no overlay</dd></div>
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">25%</dt><dd class="m-0 min-w-0 text-twr03-ink2">one quadrant of the 2×2 cell</dd></div>
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">50%</dt><dd class="m-0 min-w-0 text-twr03-ink2">two opposite quadrants — checkerboard</dd></div>
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">75%</dt><dd class="m-0 min-w-0 text-twr03-ink2">three quadrants, inverse of 25%</dd></div>
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">100%</dt><dd class="m-0 min-w-0 text-twr03-ink2">flat next palette colour</dd></div>
</dl>
</aside>
</div>
</section>@import "tailwindcss";
@theme {
--color-twr03-p0: #0f380f;
--color-twr03-p1: #306230;
--color-twr03-p2: #8bac0f;
--color-twr03-p3: #9bbc0f;
--color-twr03-bg: #f2efe6;
--color-twr03-bg: oklch(0.95 0.012 100);
--color-twr03-surface: #ffffff;
--color-twr03-surface: oklch(1 0 0);
--color-twr03-ink: #15170f;
--color-twr03-ink: oklch(0.19 0.012 120);
--color-twr03-ink2: #4e5344;
--color-twr03-ink2: oklch(0.45 0.017 120);
--color-twr03-line: #b6b9a6;
--color-twr03-line: oklch(0.77 0.02 118);
--color-twr03-acc: #2f6b12;
--color-twr03-acc: oklch(0.46 0.14 133);
--font-twr03-cond: 'Archivo', ui-sans-serif, 'Arial Narrow', Helvetica, sans-serif;
--font-twr03-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.twr-03 {
--twr-03-cell: 4px;
}
/* A feature query has no variant form, and the fallback has to reach every
patterned band at once — hence one shared hook class on the bands. */
@supports not (background: repeating-conic-gradient(#000 0% 25%, #fff 0% 50%)) {
.twr-03__dith {
background-image: repeating-linear-gradient(45deg, currentColor 0 2px, rgba(0, 0, 0, 0) 2px 4px);
color: var(--color-twr03-p3);
}
}
.twr-03:has(#twr-03-theme:checked) {
--color-twr03-bg: #14160f;
--color-twr03-bg: oklch(0.19 0.009 120);
--color-twr03-surface: #1e2117;
--color-twr03-surface: oklch(0.24 0.012 120);
--color-twr03-ink: #f0f2e7;
--color-twr03-ink: oklch(0.96 0.008 120);
--color-twr03-ink2: #a8ad99;
--color-twr03-ink2: oklch(0.74 0.016 120);
--color-twr03-line: #414635;
--color-twr03-line: oklch(0.37 0.018 120);
--color-twr03-acc: #a4d96a;
--color-twr03-acc: oklch(0.83 0.15 133);
}@import "tailwindcss";
@theme {
--color-twr03-p0: #0f380f;
--color-twr03-p1: #306230;
--color-twr03-p2: #8bac0f;
--color-twr03-p3: #9bbc0f;
--color-twr03-bg: #f2efe6;
--color-twr03-bg: oklch(0.95 0.012 100);
--color-twr03-surface: #ffffff;
--color-twr03-surface: oklch(1 0 0);
--color-twr03-ink: #15170f;
--color-twr03-ink: oklch(0.19 0.012 120);
--color-twr03-ink2: #4e5344;
--color-twr03-ink2: oklch(0.45 0.017 120);
--color-twr03-line: #b6b9a6;
--color-twr03-line: oklch(0.77 0.02 118);
--color-twr03-acc: #2f6b12;
--color-twr03-acc: oklch(0.46 0.14 133);
--font-twr03-cond: 'Archivo', ui-sans-serif, 'Arial Narrow', Helvetica, sans-serif;
--font-twr03-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.twr-03 {
--twr-03-cell: 4px;
}
/* A feature query has no variant form, and the fallback has to reach every
patterned band at once — hence one shared hook class on the bands. */
@supports not (background: repeating-conic-gradient(#000 0% 25%, #fff 0% 50%)) {
.twr-03__dith {
background-image: repeating-linear-gradient(45deg, currentColor 0 2px, rgba(0, 0, 0, 0) 2px 4px);
color: var(--color-twr03-p3);
}
}
.twr-03:has(#twr-03-theme:checked) {
--color-twr03-bg: #14160f;
--color-twr03-bg: oklch(0.19 0.009 120);
--color-twr03-surface: #1e2117;
--color-twr03-surface: oklch(0.24 0.012 120);
--color-twr03-ink: #f0f2e7;
--color-twr03-ink: oklch(0.96 0.008 120);
--color-twr03-ink2: #a8ad99;
--color-twr03-ink2: oklch(0.74 0.016 120);
--color-twr03-line: #414635;
--color-twr03-line: oklch(0.37 0.018 120);
--color-twr03-acc: #a4d96a;
--color-twr03-acc: oklch(0.83 0.15 133);
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>Compiles in the browser — perfect for a CodePen or a quick test, not for production.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-twr03-p0: #0f380f;
--color-twr03-p1: #306230;
--color-twr03-p2: #8bac0f;
--color-twr03-p3: #9bbc0f;
--color-twr03-bg: #f2efe6;
--color-twr03-bg: oklch(0.95 0.012 100);
--color-twr03-surface: #ffffff;
--color-twr03-surface: oklch(1 0 0);
--color-twr03-ink: #15170f;
--color-twr03-ink: oklch(0.19 0.012 120);
--color-twr03-ink2: #4e5344;
--color-twr03-ink2: oklch(0.45 0.017 120);
--color-twr03-line: #b6b9a6;
--color-twr03-line: oklch(0.77 0.02 118);
--color-twr03-acc: #2f6b12;
--color-twr03-acc: oklch(0.46 0.14 133);
--font-twr03-cond: 'Archivo', ui-sans-serif, 'Arial Narrow', Helvetica, sans-serif;
--font-twr03-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.twr-03 {
--twr-03-cell: 4px;
}
/* A feature query has no variant form, and the fallback has to reach every
patterned band at once — hence one shared hook class on the bands. */
@supports not (background: repeating-conic-gradient(#000 0% 25%, #fff 0% 50%)) {
.twr-03__dith {
background-image: repeating-linear-gradient(45deg, currentColor 0 2px, rgba(0, 0, 0, 0) 2px 4px);
color: var(--color-twr03-p3);
}
}
.twr-03:has(#twr-03-theme:checked) {
--color-twr03-bg: #14160f;
--color-twr03-bg: oklch(0.19 0.009 120);
--color-twr03-surface: #1e2117;
--color-twr03-surface: oklch(0.24 0.012 120);
--color-twr03-ink: #f0f2e7;
--color-twr03-ink: oklch(0.96 0.008 120);
--color-twr03-ink2: #a8ad99;
--color-twr03-ink2: oklch(0.74 0.016 120);
--color-twr03-line: #414635;
--color-twr03-line: oklch(0.37 0.018 120);
--color-twr03-acc: #a4d96a;
--color-twr03-acc: oklch(0.83 0.15 133);
}@import "tailwindcss";
@theme {
--color-twr03-p0: #0f380f;
--color-twr03-p1: #306230;
--color-twr03-p2: #8bac0f;
--color-twr03-p3: #9bbc0f;
--color-twr03-bg: #f2efe6;
--color-twr03-bg: oklch(0.95 0.012 100);
--color-twr03-surface: #ffffff;
--color-twr03-surface: oklch(1 0 0);
--color-twr03-ink: #15170f;
--color-twr03-ink: oklch(0.19 0.012 120);
--color-twr03-ink2: #4e5344;
--color-twr03-ink2: oklch(0.45 0.017 120);
--color-twr03-line: #b6b9a6;
--color-twr03-line: oklch(0.77 0.02 118);
--color-twr03-acc: #2f6b12;
--color-twr03-acc: oklch(0.46 0.14 133);
--font-twr03-cond: 'Archivo', ui-sans-serif, 'Arial Narrow', Helvetica, sans-serif;
--font-twr03-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.twr-03 {
--twr-03-cell: 4px;
}
/* A feature query has no variant form, and the fallback has to reach every
patterned band at once — hence one shared hook class on the bands. */
@supports not (background: repeating-conic-gradient(#000 0% 25%, #fff 0% 50%)) {
.twr-03__dith {
background-image: repeating-linear-gradient(45deg, currentColor 0 2px, rgba(0, 0, 0, 0) 2px 4px);
color: var(--color-twr03-p3);
}
}
.twr-03:has(#twr-03-theme:checked) {
--color-twr03-bg: #14160f;
--color-twr03-bg: oklch(0.19 0.009 120);
--color-twr03-surface: #1e2117;
--color-twr03-surface: oklch(0.24 0.012 120);
--color-twr03-ink: #f0f2e7;
--color-twr03-ink: oklch(0.96 0.008 120);
--color-twr03-ink2: #a8ad99;
--color-twr03-ink2: oklch(0.74 0.016 120);
--color-twr03-line: #414635;
--color-twr03-line: oklch(0.37 0.018 120);
--color-twr03-acc: #a4d96a;
--color-twr03-acc: oklch(0.83 0.15 133);
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@75..100,400;75..100,700&family=JetBrains+Mono:wght@400;500&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Archivo:wdth,wght@75..100,400;75..100,700&family=JetBrains+Mono:wght@400;500&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The webfonts load as
<link>tags insetup, not as an@importin the stylesheet — Tailwind emits user@importrules after its own layers, where the browser drops them. - This is the port that reads better than the original. A band called
.rt-03__band--b3tells you nothing;bg-twr03-p1plus a conic overlay in--color-twr03-p2tells you both colours and the coverage. - Palette tokens are used two ways at once: as minted utilities for the flat fill, and by variable name inside the arbitrary gradient. No hex is written twice.
--twr-03-cellis a plain custom property, and the fine ramp overrides it with[--twr-03-cell:2px]on the bar — setting a variable from the markup is itself an arbitrary property, which is the cleanest way to scope one.- The
@supportsfallback needs a shared class because it addresses six bands at once and cannot be a variant. Utilities for the happy path, one hook for the fallback group. - The four palette colours are declared as bare sRGB hex with no oklch twin: they are exact hardware values, not perceptual choices, and converting them would be wrong.
lg:grid-cols-2replaces the@media (min-width: 54rem)block, and the two ramp lengths still line up because every band isflex-1 min-w-0.
Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Dithering Patterns with Gradients
Source: https://codefronts.com/design-styles/tailwind-retro-ui/tailwind-dithering-patterns-with-gradients/
Ordered dithering is how a limited palette fakes colours it does not have: alternate two available colours in a fixed pattern and the eye averages them. Built from layered repeating-conic-gradient checkerboards over flat palette fills — and because every pattern is an arbitrary background utility, each band's coverage is legible in the markup instead of hidden behind a modifier class.
## HTML
```html
<section class="twr-03 relative block w-full min-h-svh box-border bg-twr03-bg text-twr03-ink font-twr03-cond" aria-labelledby="twr-03-title">
<h2 class="absolute size-px overflow-hidden [clip-path:inset(50%)] whitespace-nowrap" id="twr-03-title">Ordered dithering ramps built from gradients</h2>
<div class="absolute top-4 right-4 z-6">
<input class="peer absolute inset-0 size-11 m-0 opacity-0 cursor-pointer" type="checkbox" id="twr-03-theme">
<label class="grid place-items-center size-11 rounded-full border border-twr03-line bg-twr03-surface text-twr03-ink2 cursor-pointer peer-focus-visible:outline-2 peer-focus-visible:outline-twr03-acc peer-focus-visible:outline-offset-2" for="twr-03-theme">
<svg class="size-5" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12 4a8 8 0 0 0 0 16Z" fill="currentColor"/></svg>
<span class="absolute size-px overflow-hidden [clip-path:inset(50%)] whitespace-nowrap">Toggle dark surround</span>
</label>
</div>
<div class="grid grid-cols-[minmax(0,1fr)] gap-[clamp(1.5rem,1rem+2vw,2.25rem)] max-w-[68rem] mx-auto px-[clamp(0.85rem,0.5rem+2vw,2rem)] pt-[clamp(3.5rem,3rem+3vw,5rem)] pb-16">
<header class="grid gap-1.5 min-w-0">
<p class="m-0 font-twr03-mono text-[0.68rem] tracking-[0.14em] uppercase text-twr03-ink2">Palette · Game Boy DMG-01 · 4 tones, exact sRGB</p>
<h3 class="m-0 min-w-0 text-[clamp(1.35rem,1rem+2vw,2.2rem)] font-bold leading-[1.08] tracking-[-0.03em] text-balance">Four colours, twelve apparent tones</h3>
<p class="m-0 min-w-0 max-w-[52ch] text-[0.95rem] leading-relaxed text-pretty text-twr03-ink2">Every band below contains only palette colours. The intermediate tones are patterns, not blends.</p>
</header>
<div class="flex flex-wrap gap-2">
<span class="flex-none min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.03em] px-2.5 py-2 border border-twr03-line bg-twr03-p0 text-twr03-p3">#0f380f</span>
<span class="flex-none min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.03em] px-2.5 py-2 border border-twr03-line bg-twr03-p1 text-[#dff0a8]">#306230</span>
<span class="flex-none min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.03em] px-2.5 py-2 border border-twr03-line bg-twr03-p2 text-[#10290a]">#8bac0f</span>
<span class="flex-none min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.03em] px-2.5 py-2 border border-twr03-line bg-twr03-p3 text-[#10290a]">#9bbc0f</span>
</div>
<div class="grid grid-cols-[minmax(0,1fr)] gap-4 lg:grid-cols-2">
<article class="min-w-0 grid content-start gap-2.5 border border-twr03-line bg-twr03-surface p-[clamp(0.8rem,0.6rem+0.8vw,1.1rem)]" aria-labelledby="twr-03-r0">
<h4 class="m-0 min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.1em] uppercase text-twr03-ink2" id="twr-03-r0">Reference · unlimited colour</h4>
<div class="flex min-w-0 h-[clamp(64px,8vw,92px)] overflow-hidden border-2 border-[#0f380f] [background:linear-gradient(90deg,#0f380f,#306230,#8bac0f,#9bbc0f)]" aria-hidden="true"></div>
<p class="m-0 min-w-0 text-[0.82rem] leading-normal text-pretty text-twr03-ink2">A plain linear gradient. Contains thousands of colours the hardware never had.</p>
</article>
<article class="min-w-0 grid content-start gap-2.5 border border-twr03-line bg-twr03-surface p-[clamp(0.8rem,0.6rem+0.8vw,1.1rem)]" aria-labelledby="twr-03-r1">
<h4 class="m-0 min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.1em] uppercase text-twr03-ink2" id="twr-03-r1">2 colours · 2×2 Bayer</h4>
<div class="flex min-w-0 h-[clamp(64px,8vw,92px)] overflow-hidden border-2 border-[#0f380f]" aria-hidden="true">
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p0"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p0 [background-image:repeating-conic-gradient(var(--color-twr03-p3)_0%_25%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p0 [background-image:repeating-conic-gradient(var(--color-twr03-p3)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p3)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p3 [background-image:repeating-conic-gradient(var(--color-twr03-p0)_0%_25%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p3"></span>
</div>
<p class="m-0 min-w-0 text-[0.82rem] leading-normal text-pretty text-twr03-ink2">Darkest and lightest tone only. Five apparent steps from two real ones.</p>
</article>
<article class="min-w-0 grid content-start gap-2.5 border border-twr03-line bg-twr03-surface p-[clamp(0.8rem,0.6rem+0.8vw,1.1rem)]" aria-labelledby="twr-03-r2">
<h4 class="m-0 min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.1em] uppercase text-twr03-ink2" id="twr-03-r2">4 colours · adjacent-pair dither</h4>
<div class="flex min-w-0 h-[clamp(64px,8vw,92px)] overflow-hidden border-2 border-[#0f380f]" aria-hidden="true">
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p0"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p0 [background-image:repeating-conic-gradient(var(--color-twr03-p1)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p1)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p1"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p1 [background-image:repeating-conic-gradient(var(--color-twr03-p2)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p2)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p2"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p2 [background-image:repeating-conic-gradient(var(--color-twr03-p3)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p3)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p3"></span>
</div>
<p class="m-0 min-w-0 text-[0.82rem] leading-normal text-pretty text-twr03-ink2">Each pattern mixes only its two neighbouring palette entries.</p>
</article>
<article class="min-w-0 grid content-start gap-2.5 border border-twr03-line bg-twr03-surface p-[clamp(0.8rem,0.6rem+0.8vw,1.1rem)]" aria-labelledby="twr-03-r3">
<h4 class="m-0 min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.1em] uppercase text-twr03-ink2" id="twr-03-r3">8 steps · 2px cell, fine mask</h4>
<div class="flex min-w-0 h-[clamp(64px,8vw,92px)] overflow-hidden border-2 border-[#0f380f] [--twr-03-cell:2px]" aria-hidden="true">
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p0"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p0 [background-image:repeating-conic-gradient(var(--color-twr03-p1)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p1)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p1"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p1 [background-image:repeating-conic-gradient(var(--color-twr03-p2)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p2)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p2"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p2 [background-image:repeating-conic-gradient(var(--color-twr03-p3)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p3)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p3"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p3"></span>
</div>
<p class="m-0 min-w-0 text-[0.82rem] leading-normal text-pretty text-twr03-ink2">Same construction at a 2px cell. Closer to a blend, further from a period-correct look.</p>
</article>
</div>
<aside class="min-w-0 grid gap-2.5 border border-twr03-line border-l-4 border-l-twr03-acc bg-twr03-surface p-[clamp(0.85rem,0.6rem+1vw,1.2rem)]">
<h4 class="m-0 font-twr03-mono text-[0.7rem] tracking-[0.12em] uppercase text-twr03-ink2">Coverage table</h4>
<dl class="m-0 grid gap-1 text-[0.85rem]">
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">0%</dt><dd class="m-0 min-w-0 text-twr03-ink2">flat base colour, no overlay</dd></div>
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">25%</dt><dd class="m-0 min-w-0 text-twr03-ink2">one quadrant of the 2×2 cell</dd></div>
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">50%</dt><dd class="m-0 min-w-0 text-twr03-ink2">two opposite quadrants — checkerboard</dd></div>
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">75%</dt><dd class="m-0 min-w-0 text-twr03-ink2">three quadrants, inverse of 25%</dd></div>
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">100%</dt><dd class="m-0 min-w-0 text-twr03-ink2">flat next palette colour</dd></div>
</dl>
</aside>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-twr03-p0: #0f380f;
--color-twr03-p1: #306230;
--color-twr03-p2: #8bac0f;
--color-twr03-p3: #9bbc0f;
--color-twr03-bg: #f2efe6;
--color-twr03-bg: oklch(0.95 0.012 100);
--color-twr03-surface: #ffffff;
--color-twr03-surface: oklch(1 0 0);
--color-twr03-ink: #15170f;
--color-twr03-ink: oklch(0.19 0.012 120);
--color-twr03-ink2: #4e5344;
--color-twr03-ink2: oklch(0.45 0.017 120);
--color-twr03-line: #b6b9a6;
--color-twr03-line: oklch(0.77 0.02 118);
--color-twr03-acc: #2f6b12;
--color-twr03-acc: oklch(0.46 0.14 133);
--font-twr03-cond: 'Archivo', ui-sans-serif, 'Arial Narrow', Helvetica, sans-serif;
--font-twr03-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.twr-03 {
--twr-03-cell: 4px;
}
/* A feature query has no variant form, and the fallback has to reach every
patterned band at once — hence one shared hook class on the bands. */
@supports not (background: repeating-conic-gradient(#000 0% 25%, #fff 0% 50%)) {
.twr-03__dith {
background-image: repeating-linear-gradient(45deg, currentColor 0 2px, rgba(0, 0, 0, 0) 2px 4px);
color: var(--color-twr03-p3);
}
}
.twr-03:has(#twr-03-theme:checked) {
--color-twr03-bg: #14160f;
--color-twr03-bg: oklch(0.19 0.009 120);
--color-twr03-surface: #1e2117;
--color-twr03-surface: oklch(0.24 0.012 120);
--color-twr03-ink: #f0f2e7;
--color-twr03-ink: oklch(0.96 0.008 120);
--color-twr03-ink2: #a8ad99;
--color-twr03-ink2: oklch(0.74 0.016 120);
--color-twr03-line: #414635;
--color-twr03-line: oklch(0.37 0.018 120);
--color-twr03-acc: #a4d96a;
--color-twr03-acc: oklch(0.83 0.15 133);
}
```Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Dithering Patterns with Gradients
Source: https://codefronts.com/design-styles/tailwind-retro-ui/tailwind-dithering-patterns-with-gradients/
Ordered dithering is how a limited palette fakes colours it does not have: alternate two available colours in a fixed pattern and the eye averages them. Built from layered repeating-conic-gradient checkerboards over flat palette fills — and because every pattern is an arbitrary background utility, each band's coverage is legible in the markup instead of hidden behind a modifier class.
## HTML
```html
<section class="twr-03 relative block w-full min-h-svh box-border bg-twr03-bg text-twr03-ink font-twr03-cond" aria-labelledby="twr-03-title">
<h2 class="absolute size-px overflow-hidden [clip-path:inset(50%)] whitespace-nowrap" id="twr-03-title">Ordered dithering ramps built from gradients</h2>
<div class="absolute top-4 right-4 z-6">
<input class="peer absolute inset-0 size-11 m-0 opacity-0 cursor-pointer" type="checkbox" id="twr-03-theme">
<label class="grid place-items-center size-11 rounded-full border border-twr03-line bg-twr03-surface text-twr03-ink2 cursor-pointer peer-focus-visible:outline-2 peer-focus-visible:outline-twr03-acc peer-focus-visible:outline-offset-2" for="twr-03-theme">
<svg class="size-5" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12 4a8 8 0 0 0 0 16Z" fill="currentColor"/></svg>
<span class="absolute size-px overflow-hidden [clip-path:inset(50%)] whitespace-nowrap">Toggle dark surround</span>
</label>
</div>
<div class="grid grid-cols-[minmax(0,1fr)] gap-[clamp(1.5rem,1rem+2vw,2.25rem)] max-w-[68rem] mx-auto px-[clamp(0.85rem,0.5rem+2vw,2rem)] pt-[clamp(3.5rem,3rem+3vw,5rem)] pb-16">
<header class="grid gap-1.5 min-w-0">
<p class="m-0 font-twr03-mono text-[0.68rem] tracking-[0.14em] uppercase text-twr03-ink2">Palette · Game Boy DMG-01 · 4 tones, exact sRGB</p>
<h3 class="m-0 min-w-0 text-[clamp(1.35rem,1rem+2vw,2.2rem)] font-bold leading-[1.08] tracking-[-0.03em] text-balance">Four colours, twelve apparent tones</h3>
<p class="m-0 min-w-0 max-w-[52ch] text-[0.95rem] leading-relaxed text-pretty text-twr03-ink2">Every band below contains only palette colours. The intermediate tones are patterns, not blends.</p>
</header>
<div class="flex flex-wrap gap-2">
<span class="flex-none min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.03em] px-2.5 py-2 border border-twr03-line bg-twr03-p0 text-twr03-p3">#0f380f</span>
<span class="flex-none min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.03em] px-2.5 py-2 border border-twr03-line bg-twr03-p1 text-[#dff0a8]">#306230</span>
<span class="flex-none min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.03em] px-2.5 py-2 border border-twr03-line bg-twr03-p2 text-[#10290a]">#8bac0f</span>
<span class="flex-none min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.03em] px-2.5 py-2 border border-twr03-line bg-twr03-p3 text-[#10290a]">#9bbc0f</span>
</div>
<div class="grid grid-cols-[minmax(0,1fr)] gap-4 lg:grid-cols-2">
<article class="min-w-0 grid content-start gap-2.5 border border-twr03-line bg-twr03-surface p-[clamp(0.8rem,0.6rem+0.8vw,1.1rem)]" aria-labelledby="twr-03-r0">
<h4 class="m-0 min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.1em] uppercase text-twr03-ink2" id="twr-03-r0">Reference · unlimited colour</h4>
<div class="flex min-w-0 h-[clamp(64px,8vw,92px)] overflow-hidden border-2 border-[#0f380f] [background:linear-gradient(90deg,#0f380f,#306230,#8bac0f,#9bbc0f)]" aria-hidden="true"></div>
<p class="m-0 min-w-0 text-[0.82rem] leading-normal text-pretty text-twr03-ink2">A plain linear gradient. Contains thousands of colours the hardware never had.</p>
</article>
<article class="min-w-0 grid content-start gap-2.5 border border-twr03-line bg-twr03-surface p-[clamp(0.8rem,0.6rem+0.8vw,1.1rem)]" aria-labelledby="twr-03-r1">
<h4 class="m-0 min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.1em] uppercase text-twr03-ink2" id="twr-03-r1">2 colours · 2×2 Bayer</h4>
<div class="flex min-w-0 h-[clamp(64px,8vw,92px)] overflow-hidden border-2 border-[#0f380f]" aria-hidden="true">
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p0"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p0 [background-image:repeating-conic-gradient(var(--color-twr03-p3)_0%_25%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p0 [background-image:repeating-conic-gradient(var(--color-twr03-p3)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p3)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p3 [background-image:repeating-conic-gradient(var(--color-twr03-p0)_0%_25%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p3"></span>
</div>
<p class="m-0 min-w-0 text-[0.82rem] leading-normal text-pretty text-twr03-ink2">Darkest and lightest tone only. Five apparent steps from two real ones.</p>
</article>
<article class="min-w-0 grid content-start gap-2.5 border border-twr03-line bg-twr03-surface p-[clamp(0.8rem,0.6rem+0.8vw,1.1rem)]" aria-labelledby="twr-03-r2">
<h4 class="m-0 min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.1em] uppercase text-twr03-ink2" id="twr-03-r2">4 colours · adjacent-pair dither</h4>
<div class="flex min-w-0 h-[clamp(64px,8vw,92px)] overflow-hidden border-2 border-[#0f380f]" aria-hidden="true">
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p0"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p0 [background-image:repeating-conic-gradient(var(--color-twr03-p1)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p1)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p1"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p1 [background-image:repeating-conic-gradient(var(--color-twr03-p2)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p2)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p2"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p2 [background-image:repeating-conic-gradient(var(--color-twr03-p3)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p3)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p3"></span>
</div>
<p class="m-0 min-w-0 text-[0.82rem] leading-normal text-pretty text-twr03-ink2">Each pattern mixes only its two neighbouring palette entries.</p>
</article>
<article class="min-w-0 grid content-start gap-2.5 border border-twr03-line bg-twr03-surface p-[clamp(0.8rem,0.6rem+0.8vw,1.1rem)]" aria-labelledby="twr-03-r3">
<h4 class="m-0 min-w-0 font-twr03-mono text-[0.7rem] tracking-[0.1em] uppercase text-twr03-ink2" id="twr-03-r3">8 steps · 2px cell, fine mask</h4>
<div class="flex min-w-0 h-[clamp(64px,8vw,92px)] overflow-hidden border-2 border-[#0f380f] [--twr-03-cell:2px]" aria-hidden="true">
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p0"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p0 [background-image:repeating-conic-gradient(var(--color-twr03-p1)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p1)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p1"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p1 [background-image:repeating-conic-gradient(var(--color-twr03-p2)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p2)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p2"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] twr-03__dith bg-twr03-p2 [background-image:repeating-conic-gradient(var(--color-twr03-p3)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p3)_0%_75%,rgba(0,0,0,0)_0%_100%)]"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p3"></span>
<span class="flex-1 min-w-0 [background-size:var(--twr-03-cell)_var(--twr-03-cell)] bg-twr03-p3"></span>
</div>
<p class="m-0 min-w-0 text-[0.82rem] leading-normal text-pretty text-twr03-ink2">Same construction at a 2px cell. Closer to a blend, further from a period-correct look.</p>
</article>
</div>
<aside class="min-w-0 grid gap-2.5 border border-twr03-line border-l-4 border-l-twr03-acc bg-twr03-surface p-[clamp(0.85rem,0.6rem+1vw,1.2rem)]">
<h4 class="m-0 font-twr03-mono text-[0.7rem] tracking-[0.12em] uppercase text-twr03-ink2">Coverage table</h4>
<dl class="m-0 grid gap-1 text-[0.85rem]">
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">0%</dt><dd class="m-0 min-w-0 text-twr03-ink2">flat base colour, no overlay</dd></div>
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">25%</dt><dd class="m-0 min-w-0 text-twr03-ink2">one quadrant of the 2×2 cell</dd></div>
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">50%</dt><dd class="m-0 min-w-0 text-twr03-ink2">two opposite quadrants — checkerboard</dd></div>
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">75%</dt><dd class="m-0 min-w-0 text-twr03-ink2">three quadrants, inverse of 25%</dd></div>
<div class="flex items-baseline gap-3 min-w-0"><dt class="m-0 flex-none w-14 font-twr03-mono tabular-nums text-twr03-acc">100%</dt><dd class="m-0 min-w-0 text-twr03-ink2">flat next palette colour</dd></div>
</dl>
</aside>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-twr03-p0: #0f380f;
--color-twr03-p1: #306230;
--color-twr03-p2: #8bac0f;
--color-twr03-p3: #9bbc0f;
--color-twr03-bg: #f2efe6;
--color-twr03-bg: oklch(0.95 0.012 100);
--color-twr03-surface: #ffffff;
--color-twr03-surface: oklch(1 0 0);
--color-twr03-ink: #15170f;
--color-twr03-ink: oklch(0.19 0.012 120);
--color-twr03-ink2: #4e5344;
--color-twr03-ink2: oklch(0.45 0.017 120);
--color-twr03-line: #b6b9a6;
--color-twr03-line: oklch(0.77 0.02 118);
--color-twr03-acc: #2f6b12;
--color-twr03-acc: oklch(0.46 0.14 133);
--font-twr03-cond: 'Archivo', ui-sans-serif, 'Arial Narrow', Helvetica, sans-serif;
--font-twr03-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.twr-03 {
--twr-03-cell: 4px;
}
/* A feature query has no variant form, and the fallback has to reach every
patterned band at once — hence one shared hook class on the bands. */
@supports not (background: repeating-conic-gradient(#000 0% 25%, #fff 0% 50%)) {
.twr-03__dith {
background-image: repeating-linear-gradient(45deg, currentColor 0 2px, rgba(0, 0, 0, 0) 2px 4px);
color: var(--color-twr03-p3);
}
}
.twr-03:has(#twr-03-theme:checked) {
--color-twr03-bg: #14160f;
--color-twr03-bg: oklch(0.19 0.009 120);
--color-twr03-surface: #1e2117;
--color-twr03-surface: oklch(0.24 0.012 120);
--color-twr03-ink: #f0f2e7;
--color-twr03-ink: oklch(0.96 0.008 120);
--color-twr03-ink2: #a8ad99;
--color-twr03-ink2: oklch(0.74 0.016 120);
--color-twr03-line: #414635;
--color-twr03-line: oklch(0.37 0.018 120);
--color-twr03-acc: #a4d96a;
--color-twr03-acc: oklch(0.83 0.15 133);
}
```How this works
Dithering trades spatial resolution for colour resolution. If the palette has four greys and you need a fifth, you interleave the two nearest ones in a regular pattern and let the eye average at viewing distance. A 50% checkerboard of black and white reads as mid grey. That is the whole idea, and it is why 1-bit and 4-colour machines could still show a gradient.
Ordered dithering means the pattern is fixed, which is exactly why it ports. Bayer dithering uses a threshold matrix, so the same input tone always yields the same dot arrangement — and a fixed pattern is a repeating gradient, which is a value, which can be a utility. Error diffusion (Floyd–Steinberg) instead pushes each pixel's rounding error into its neighbours: per-pixel state, no CSS equivalent, no utility equivalent either.
The construction is a coverage stack, and the port makes it readable. Each band sets a flat palette background, then paints its neighbour over it covering one, two or three quadrants of the cell:
<span class="flex-1 min-w-0 bg-twr03-p1
[background-image:repeating-conic-gradient(var(--color-twr03-p2)_0%_25%,rgba(0,0,0,0)_0%_50%,var(--color-twr03-p2)_0%_75%,rgba(0,0,0,0)_0%_100%)]
[background-size:var(--twr-03-cell)_var(--twr-03-cell)]"></span>In the CSS version this band is .rt-03__band--b3 — a name you have to go look up. Here the two colours involved and the coverage are in the element. That is the clearest win in the whole collection, and it is worth noticing that it comes from arbitrary values, not from Tailwind's scales.
@theme colours pull double duty. --color-twr03-p2 mints bg-twr03-p2 for the flat fill, and the same variable is referenced by name inside the gradient. One token, two syntaxes, no duplicated hex — which is what keeps the ramps honest: no band can contain a colour the palette does not have.
The feature query stays in CSS, and it needs a hook. repeating-conic-gradient is old but not universal, so a @supports not (...) block swaps in a diagonal linear-gradient dither. A feature query has no variant form, and it must reach every patterned band at once — so the bands carry a twr-03__dith class purely as a selector target. That is the honest pattern for feature fallbacks: utilities for the happy path, one class for the group the fallback addresses.
Be honest about the limit. This is a decorative approximation: the pattern is uniform within each band, so transitions read as steps rather than dissolving. It also costs real paint time — a full-viewport dithered gradient is a large tiled paint that repeats on every repaint, and at that size a pre-rendered PNG is the correct tool.
Make it yours
- Set
--twr-03-cellto 2px for a fine mask that nearly dissolves, or 8px for a coarse dot that reads as deliberate texture; the fine ramp already overrides it locally. - Swap the palette by editing
--color-twr03-p0throughp3in@theme; both the flat fills and the overlays follow, because they are the same tokens. - Rotate the pattern by adding
from_45deginside the arbitrary conic gradient for a diamond dither instead of a square one. - Reorder the bands freely — the coverage percentages are independent of order, and each band now states its own coverage.
- Add a 12.5% step with an 8px cell covering one quadrant of a quarter, which is where an 8×8 Bayer matrix finds its extra levels.
- Drop a single band over a photo with
mix-blend-multiplyfor a printed-halftone feel without touching the image.
Gotchas — read before shipping
- Arbitrary gradients cannot contain spaces. Every stop needs the underscore escape (
0%_25%); one literal space and the band silently paints flat. - A
@supportsquery is not a variant. The conic fallback has to live in CSS, and the bands need a shared class for it to select. - This is ordered dithering, not error diffusion. Smooth photographic sources will band; do not expect Floyd–Steinberg from a repeating gradient.
- Large dithered areas are expensive to paint. A full-page tiled conic pattern repaints on scroll and shows in a profile immediately — keep it to panels and headers.
- A 1px or 2px cell interacts with fractional device pixel ratios and produces moiré. Test at 1.25× and 1.5×, or keep the cell at 4px and above.
- Dithered text backgrounds wreck contrast measurement: the effective background is neither colour. All body copy here sits on a flat fill for that reason.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
repeating-conic-gradient lands at Chrome 69 / Safari 12.1 / Firefox 83 and is gated with @supports, falling back to a diagonal repeating-linear-gradient that reads as a coarser dither rather than breaking. The real floor is Tailwind v4's generated sheet at Chrome 111+, Safari 16.4+ and Firefox 128+. The period palette itself is plain sRGB hex and paints everywhere.