A shader background is a program that runs once per pixel, sixty times a second, behind your headline. That sentence is the whole cost model, and it is worth holding on to, because it explains both why the results look better than anything CSS can do and why the same component can be free on a laptop and ruinous on a phone.
119 public components on 21st have "shader" in the name and 397 carry the WebGL tag. Below are the shapes that recur, and the four settings that decide whether one is shippable.
The full-bleed background
The largest group and the reason most people arrive. Shader Animation by Ali Imam is the most-bookmarked one in the catalogue, with WebGL Shader and Shader Lines by the same author as the neighbouring variants.
Shader Background and Animated Shader Background by Le Thanh are the two most-installed general-purpose backgrounds, and Background Paper Shaders by reuno-ui wraps the Paper Shaders set, which is the closest thing this space has to a standard library.
The shader hero
The same technique with the composition built in: Animated Shader Hero by Ravi Katiyar is a full hero section rather than a backdrop you still have to lay out on top of.
That distinction matters more than it sounds. A raw background leaves you to solve contrast, and a shader is the hardest possible surface to put text on, because its brightness changes over time. A hero component that ships with the overlay already tuned has solved the part that takes the longest.
The smaller surfaces
Wrap Shader and Feature Shader Cards by shadway put the effect inside a card rather than behind the page. This is the version worth reaching for first: one small canvas costs a fraction of a full-screen one, and the effect still registers.




The four settings that decide whether it ships
Resolution, not pixels. A shader on a 2x display renders four times the pixels of the same canvas on a 1x screen. Cap devicePixelRatio at 1.5, or render at half resolution and let the browser scale the canvas up with CSS. For a blurred, soft effect nobody can tell, and it is often a three-times saving.
Frame rate. Most background shaders look identical at 30fps. Halving the loop halves the GPU work and the battery cost, and a soft drifting gradient has no motion detail that needs 60.
Visibility. An IntersectionObserver that stops the loop when the canvas scrolls away, and a visibilitychange listener that stops it when the tab is hidden. Without those, a hero shader keeps rendering while someone reads the pricing page.
A fallback that is not a blank box. WebGL can fail: an old device, a blocked context, a browser with hardware acceleration off. Ship a static image or a CSS gradient behind the canvas so the section still looks finished when the shader never starts.
Contrast, which is the part that gets skipped
Text on a moving surface is the hardest legibility problem on a landing page, because the contrast ratio is different in every frame. Three things make it survivable.
Put a scrim between the shader and the text: a semi-opaque layer, or a gradient from transparent to the background colour behind the headline. Test against the brightest frame the shader can produce, not the screenshot you happened to take. And keep the busiest part of the effect away from the text, which usually means pushing the interesting motion to the edges of the canvas rather than the middle.




Writing your own
If you are building rather than borrowing, the shape is small. A full-screen quad, a fragment shader, and three uniforms: time, resolution and pointer position. Everything in this article is that plus a noise function.
The shader builder covers the same ground without the boilerplate: 212 community shaders to start from, live editing, and an export that produces a component rather than a snippet.
Where else to look
The honest list of alternatives, because the answer is not always us:
| Source | Best for | Trade-off |
|---|---|---|
| Paper Shaders | Ready-made mesh gradients, grain and warps with sensible defaults | A fixed set of effects |
| React Three Fiber | Shaders inside a real scene with cameras and geometry | The largest bundle in this table |
| ogl / raw WebGL | One quad and one fragment shader, a few kilobytes | You write the plumbing |
| CSS gradients | Everything that does not need per-pixel maths | No noise, no warp, no time |
| 21st | Finished backgrounds, shader heroes and card-sized effects | Quality varies by author, so preview before you take it |
Taking one
Every component page has a live preview and the code. Installing goes through the shadcn CLI against our registry:
That key comes from your 21st account, and installs require a membership. Set API_KEY_21ST once in your shell and the command works for anything in the catalogue. The 21st MCP covers the same ground without leaving the editor: ask Claude, Cursor or Codex for a shader background, get the previews inline, and let the agent write the file.
Frequently asked
- Are WebGL shader backgrounds bad for performance?
- Not inherently, but the defaults are. Four settings do most of the work: cap devicePixelRatio at about 1.5 or render at half resolution, halve the frame rate since most background effects look identical at 30fps, stop the loop when the canvas scrolls offscreen or the tab is hidden, and ship a static fallback for devices where WebGL never starts.
- How do you keep text readable over a shader?
- Put a scrim between them: a semi-opaque layer or a gradient into the background colour behind the headline. Test against the brightest frame the shader can produce rather than a screenshot, because the contrast ratio changes every frame. Keep the busiest motion at the edges of the canvas rather than behind the words.
- Do I need Three.js for a shader background?
- No. A background shader is a full-screen quad, a fragment shader and three uniforms: time, resolution and pointer. Raw WebGL or a small library like ogl covers it in a few kilobytes. Three.js earns its size when the shader lives inside a real scene with geometry and a camera.
- What happens if WebGL is unavailable?
- The canvas renders nothing and the section looks broken, which happens on older devices, with hardware acceleration disabled, or when too many contexts already exist on the page. Put a static image or a CSS gradient behind the canvas so the layout is finished either way.