Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Shaders

Pro

Fire 3D Shader for React

A single flame drawn in 3D on the GPU: it rises from a blue root, twists as it climbs and throws off swirling licks, yellow-white at its heart and orange-red at its edges. For React with Base UI, when a dark hero, a launch or a product card wants a living flame at its center.

Framework

Fire 3D Shader draws one flame, the way a camera would see a real one: it rises from a small blue root near the bottom of the box, swells into a yellow-white heart, and tapers to a tip that twists, leans and tears into thin, swirling licks of orange and red, with a warm glow on the dark around it. The flame is a volume, not a picture. For every pixel, a WGSL fragment shader on WebGPU sends a ray through a twisting, teardrop-shaped sheet of fire that five layers of turbulence fold over on itself, and adds up light wherever the ray passes close to it: where it grazes a fold, a bright lick appears.

Use it at the center of a dark hero, a launch or "hot right now" section, a game or a candle-lit brand. The flame takes the middle third of the box, so put your copy to the sides or above it. For a bed of coals with no flame, use Embers Shader; for a low wall of fire with sparks rising, Sparks Drifting Shader; for lava, Magma Shader; and for a fire in plain CSS, with no GPU, the Fireplace background. It runs only while it's on screen, holds a still frame with reduced motion, and shows a soft CSS flame in browsers without WebGPU.

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Usage

import { Fire3dShader } from "@/components/ui/fire-3d-shader";
<Fire3dShader className="flex min-h-[32rem] items-start justify-center pt-10">
  <h1 className="text-5xl font-semibold text-white">Ignite</h1>
</Fire3dShader>

Fire 3D Shader is a container: your content sits on top of the flame, 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 background is near black in both color schemes, so put white or light text on it, above the flame's tip or to either side.

Demos

Spirit flame

The flame's colors are props: flameColor="#22a6ff" turns its body blue, coreColor="#e6fbff" its heart icy white, and baseColor="#a855f7" its root violet. turbulence={1.3} makes it wilder, with more licks near the tip.

Preview width

In a card

The flame is sized to the box's height, so it keeps its shape in a card. height={0.9} lets it fill more of a short box, and turbulence={0.7} calms it toward a steady, candle-like flame.

Preview width

Performance

About 2 ms of GPU time a frame at 1280×720 on an M2 Max laptop, measured between 1.7 and 3 ms; slower GPUs take several times longer. Only the middle of the box, where the flame can reach, is ray marched: 40 steps of five turbulence layers per pixel. The licks are fine lines, so it renders at full resolution by default; quality={0.5} costs a quarter as much and softens them into a glow. 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 (about 50 KB gzipped) 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 flame: a soft ellipse in the core and flame colors, a touch of the root color under it, and the background color around it, 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 flame is decoration: it's hidden from assistive tech and lets every click through to your content. With reduced motion it draws one still frame, two and a half seconds in, and stops. Nothing flashes: the flame sways and its licks swirl, but its brightness doesn't jump. White text stays above 18:1 on the outer thirds of the box and on the top fifth, across every frame we measured; over the whole box it reaches 4.5:1 on 94%, so keep text off the flame itself.

FAQ

Is it real 3D fire?

It's a 3D shape, not a fluid simulation. Each pixel's ray steps through a teardrop-shaped sheet that twists around its axis, folded over itself by five layers of sine turbulence that drift upward, and it gathers light wherever it passes near the sheet. Since the sheet is 3D, the flame turns and folds with depth as it moves, but nothing burns or flows: the motion is the turbulence drifting.

How do I change the flame's colors?

coreColor sets the heart, where the folds pile up and the light is strongest; flameColor the body and licks, with the faint edges a darker, redder shade of it; baseColor the root; and backgroundColor the space around it. They take any CSS color and follow a theme switch. The Spirit flame demo above is a blue one.

Can I make it taller or calmer?

height sets how tall it stands, from 0.4 to 1 of the box's height. turbulence sets how wildly it twists: 0.5 is a calm, candle-like flame, 1.5 a roaring one whose tip tears into many licks. intensity sets its brightness, from 0 to 2, and speed how fast it all moves.

Does it work on a light page?

The box is always opaque, so the flame keeps its dark surround on a light page too, where it reads as a dark panel. For a softer look in a light theme, set backgroundColor to a dark warm tone such as #2a1a14, or a deep tint of your brand color; keep it dark, or the flame loses its glow.

Will it slow my page down?

It costs about 2 ms of GPU time a frame at 1280×720 on an M2 Max laptop. Only the middle of the box is ray marched, and the CPU only sets a few numbers each frame. It stops when it's off screen. On a slow GPU or a large screen, quality={0.5} renders a quarter of the pixels; the licks soften but the flame keeps its shape. turbulence and height don't change the cost.

What happens in browsers without WebGPU?

The box keeps its CSS still, a soft flame-shaped glow in the core and flame colors on the background color, so the page still looks finished. Nothing errors: the root's data-state reads unsupported.

Credits

Inspired by a fire shader (opens in a new tab) by Xor on Shadertoy, through shadcn.io's Fire 3D. This is a new shader written from a description of the technique, not a port: a ray marched through turbulent fire that gathers light near a hollow shape. The flame's shape, its blue root, the twist, the turbulence, the coloring, the props and the code are ours.

API Reference

Fire3dShader

data-slot="fire-3d-shader"

PropType
backgroundColor?string

The space around the flame. Any CSS colour. @default "#0a0605".

Default
"#0a0605"
baseColor?string

The flame's root, where it leaves the burner. Any CSS colour. @default "#3a5cff".

Default
"#3a5cff"
coreColor?string

The hottest middle of the flame. Any CSS colour. @default "#ffe7a3".

Default
"#ffe7a3"
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.

flameColor?string

The flame's body and its licks; its edges are a darker, redder shade of it. Any CSS colour. @default "#ff7417".

Default
"#ff7417"
height?number

How tall the flame stands, as a share of the box's height, from 0.4 to 1. @default 0.75.

Default
0.75
intensity?number

How bright the flame burns, from 0 (out) to 2. @default 1.

Default
1
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.

speed?number

Animation speed: 1 is normal, 0 holds the frame. @default 1.

time?number

A fixed moment, in seconds: draws it and doesn't animate.

turbulence?number

How wildly the flame twists and licks, from 0.5 (a calm candle-like column) to 1.5 (a roaring one). @default 1.

Default
1
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.

All 101 shaders