shadcn.io is not affiliated with official shadcn/ui
Synthwave Canyon Shader flies you down a canyon at sunset, 80s style. A huge sun fills the top of the frame, yellow at its crown and hot pink at its base, its lower third cut by thin stripes inside a soft corona. In front, ridge after ridge of dark hills, each traced by a glowing lavender line, recede toward the horizon, and the camera wobbles gently as it flies. A WGSL fragment shader on WebGPU draws it with no 3D model: it slices the canyon into 24 flat layers, finds where each pixel's ray crosses each one, and blends them front to back.
Use it behind a music, gaming or retro launch hero, or a full-screen intro with an outrun mood. For a perspective grid in plain CSS, with no GPU, use the Retro Grid background; for a flight through layers of a different kind, Starry Planes Shader; for a daylit landscape, Desert Sand Shader. It runs only while it's on screen, holds a still frame with reduced motion, and shows a gradient of the same sun and haze in browsers without WebGPU.
Installation
Usage
import {
SynthwaveCanyonShader,
} from "@/components/ui/synthwave-canyon-shader";<SynthwaveCanyonShader className="flex min-h-[32rem] items-end justify-center pb-16">
<h1 className="text-5xl font-semibold text-white drop-shadow-[0_0_12px_#ff00ff]">
Night drive
</h1>
</SynthwaveCanyonShader>Synthwave Canyon Shader is a container: your content sits on top of the canyon, in normal flow. It fills its own box, so give it a height or content. For a backdrop behind the whole page, render it empty with className="fixed inset-0 -z-10". The scene is the same in both color schemes. White text reads on the purple floor in the lower part, where it passes 4.5:1 on 88% of the area, though the neon lines cross it; on the sun only dark text reads. For a centered headline, put it on a panel such as bg-black/60.
Demos
Scanlines
scanlines draws CRT scanlines across the whole frame, 4 CSS pixels apart at any screen density, for an old-monitor look. speed={0.5} halves the flight, which suits a calmer page.
In a card
sunColor="#ff3d81" and glowColor="#00e5ff" turn the sun pink over a cyan horizon, and the glow color tints the sky with it. depth={16} ends the canyon sooner, in the sun's glow, which suits a small box.
Performance
About 1.4 ms of GPU time a frame at 1280×720, measured on an M2 Max laptop at full quality. Slower GPUs take several times longer. The ridges cover most pixels within a few slices, so depth saves less than you'd think: depth={12} costs about a fifth less. On a slow GPU, quality={0.5} renders at half resolution, a quarter of the pixels; the neon lines soften but keep their glow. scanlines costs almost nothing. The animation stops when the shader scrolls out of view, and the browser pauses it in a hidden tab. Every shader on a page shares one GPU device and one frame loop, and vgpu loads only when the first one mounts.
Browser support
The shader needs WebGPU: Chrome and Edge, Safari 26 and later, and Firefox on Windows and macOS. Elsewhere, and until the first frame, the box shows a CSS gradient of the same sun and haze, so the layout never jumps. data-state on the root reads unsupported there, if you want to style around it. See Shader Canvas.
Accessibility
The canyon is decoration: it's hidden from assistive tech and lets every click through to your content. With reduced motion it draws one still frame, the sun over the canyon, and stops. Nothing flashes: a new ridge rises out of the haze every two seconds at the default speed, and the lines glide rather than blink, even at speed={3}. For text, white needs the lower part of the frame or a panel: across the flight, white text on a bg-black/60 panel stayed above 5.7:1 everywhere, and black text reads on the sun at 7.9:1 or more on 95% of it.
FAQ
How is the canyon drawn without 3D models?
It's 24 flat slices across the canyon, half a unit apart. Each slice's outline is a ridge profile made of fractal value noise, low in the middle and high at the sides. For every pixel, the shader finds where the ray crosses each slice, front to back, and draws a glowing line at the ridge over a dark fill below it. It stops as soon as the slices in front cover the pixel, so most pixels touch only a few.
Can I change the flight speed?
speed scales the flight: at 1 a new ridge comes in every two seconds, 0.5 halves it, and 0 holds the current frame. paused holds it too, and time draws one fixed moment, in seconds, which is handy for a poster or for tying the flight to scroll.
How do I add CRT scanlines?
Set scanlines. The lines sit 4 CSS pixels apart at any screen density and brighten the frame slightly between them, like an old monitor. They cost almost nothing: one sine per pixel.
Can I recolor the sun?
Yes. sunColor sets the top of the sun and glowColor its base, where the stripes are; the sun blends from one to the other, and the glow color also tints the sky and the corona. Both take any CSS color and follow a theme switch, so var(--primary) works. The ridges keep their own lavender-to-cyan lines.
Will it slow my page down?
It looks 3D, but it's light: about 1.4 ms of GPU time a frame at 1280×720 on an M2 Max laptop, because it crosses flat slices instead of ray marching a surface. It stops when it's off screen. On a slow GPU or a large screen, quality={0.5} renders a quarter of the pixels. A lower depth helps less: depth={12} saves about a fifth.
Credits
Based on Synthwave canyon (opens in a new tab) by mrange, released under CC0, through shadcn.io's version. The HSV-to-RGB conversion is by Sam Hocevar (WTFPL) and the smooth minimum by Inigo Quilez (MIT); both keep their credit lines in the WGSL. What changed in the port:
- Rewrites the helpers of unknown licence. An integer hash (lowbias32, by Chris Wellons, public domain) and our own value noise replace the sine hash, so the ridges have different shapes than the original's at a given moment; the flight, the canyon and the sun are the same. With the original's hash swapped back in, the port matches the original pixel for pixel. Front-to-back blending replaces the alpha-blend helpers, WGSL's built-in
tanhreplaces the approximation, and a plain floored modulo cuts the sun's stripes. - Drops the 4-second fade-in from black (the canvas fades in itself) and
flightHeight, which only cut off the ray above a height and didn't move the camera. - Renames
crtEffecttoscanlines, now sized in CSS pixels so a high-density screen doesn't halve them, andterrainDepthtodepth, capped at 24 (more drew nothing new). AddssunColorandglowColor.
API Reference
SynthwaveCanyonShader
data-slot="synthwave-canyon-shader"
depth?number
How many ridges ahead are drawn, from 8 to 24: fewer ends the canyon sooner, in the sun's glow, and costs less. @default 24.
- Default
24
fallback?string
What shows until the first frame and in browsers without WebGPU: a CSS
background value (gradients, sizes, a colour) that looks like the
shader. It can use the colour props' --shader-<field> variables.
glowColor?string
The base of the sun, where its stripes are, and the haze over the sky. Any CSS colour. @default "#ff00ff".
- Default
"#ff00ff"
interactive?boolean
Whether u.pointer follows the pointer. @default false.
paused?boolean
Holds the current frame. @default false.
quality?number
Render scale, from 0.25 to 1, of the screen's pixels (capped at 2×). @default 1.
scanlines?boolean
Draws CRT scanlines, 4 CSS pixels apart. @default false.
- Default
false
speed?number
Animation speed: 1 is normal, 0 holds the frame. @default 1.
sunColor?string
The top of the sun, which blends into glowColor toward the horizon. Any CSS colour. @default "#ffff00".
- Default
"#ffff00"
time?number
A fixed moment, in seconds: draws it and doesn't animate.
render?ReactElement | ((props: object, state: object) => ReactElement)
Replace the host element or compose it with another component.
- Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string
Forwarded to the part.
Related
- Pro


CRT Phosphor Shader
Digital & retroThe same synth sunset, on an old screen
- Pro


Starry Planes Shader
SpaceAnother flight through layers
- Pro


Desert Sand Shader
Water & landscapesA daylit landscape
- Pro


Oldschool Tube Shader
Tunnels & 3DA demoscene flight down a metal tube
- Pro


Pixel Sort Shader
Digital & retroA dusk melted into streaks


Ridgeline Shader
Digital & retroStacked ridgelines, monochrome and free