Four pill-shaped glass cards named Ember, Solar, Breeze and Bloom on a reflective dark floor; the Ember card in the centre is on fire.

Showcase · Three.js · WebGPU · TSL

Elemental Cards: interactive 3D card effects with Three.js and WebGPU

Four glass cards, four elements. Scroll to light them one by one, move your cursor to play with the effects and click the lit card to ignite it. Everything you see is rendered live in your browser.

01 · Element

Ember

Fire · Courage

Flames climb over the top of the card and lick down its sides while embers and tiny hollow triangles drift upward. Move the cursor and the fire leans with it.

  • Fire shader
  • Distance field
  • GPU particles

02 · Element

Solar

Sun · Vitality

A white-hot rim ignites first, then golden rays fan out while sparks and small rings float away. The rays gather on the side where your cursor is.

  • Glow effect
  • God rays
  • Bloom

03 · Element

Breeze

Air · Clarity

Fine teal streamlines wrap the card like air around an obstacle. Your cursor becomes a second obstacle: the lines bend around it and speed up.

  • Flow lines
  • Noise warp
  • Animated dashes

04 · Element

Bloom

Heart · Warmth

A lotus opens behind the card petal by petal, glowing at its edges, while pink motes rise. The petals breathe and sway away from the cursor.

  • 3D petals
  • Staggered easing
  • Soft glow

Want cards like these on your site?

I design and build interactive 3D sections for landing pages and products with Three.js, React and Next.js, matched to your brand and your content.

Showcase · Three.js · WebGPU · TSL

What you're looking at

Elemental Cards is an interactive 3D card carousel. Each card is a pill of smoked glass with a printed icon, name and two keywords. When a card reaches the centre, its face turns into a drifting iridescent gradient and its element comes alive around it: fire, sunlight, wind or a blooming lotus.

The scene is not a video. It is drawn 60 to 120 times per second by your graphics card with Three.js and the new WebGPU renderer, and it reacts to scrolling, the cursor and clicks. On browsers without WebGPU it switches to WebGL 2 automatically.

elements, each with its own shader effect
4elements, each with its own shader effect
particles animated on the GPU
220+particles animated on the GPU
noise texture shared by every effect
1noise texture shared by every effect
renderers: WebGPU with a WebGL 2 fallback
2renderers: WebGPU with a WebGL 2 fallback

The four cards

Fire, sun glow, wind and a lotus: four shader effects

Every effect is drawn around the card in card space, so it tilts with the card and follows it through the carousel. Here is what each one does and the technique behind it.

Ember: a fire shader with embers

Flames rise highest above the card and stay low along its sides. Embers drift up and fade, and a handful of hollow triangles float through the fire. Moving the cursor quickly sideways makes the flames lean against the motion.

Technique: The flame starts from the distance to the card outline. Three noise layers scroll upwards at different speeds and break the smooth gradient into tongues. A colour ramp maps the heat from deep red through orange to a pale core.

Solar: a glow effect with god rays

The rim ignites before the face fills with colour, then rays fan out and sparks and little rings drift away from the edge. Rays and glow gather on the side nearest to your cursor.

Technique: Two exponential falloffs from the distance field give the hot rim and the wide glow. The rays are two noise bands read around the card by angle; because the noise texture tiles, the circle closes without a seam.

Breeze: flow lines around an obstacle

Thin streamlines hug the card, brighter ones mixed with soft teal ones, with dashes travelling from left to right. The cursor pushes the air aside, and the wind speeds up near it and after a click.

Technique: The lines are contours of a sideways-stretched distance field, warped by slow noise. Each contour gets its own random speed and dash length. A separate clock drives the dashes so they can accelerate without jumping.

Bloom: a lotus made of 3D petals

Thirteen petals in four layers unfold behind the card, the inner ones first. They glow at the edges, breathe slowly and lean away from the cursor, while pink motes rise around the flower.

Technique: Each petal is a curved mesh shaped on the CPU once. Activation drives a staggered ease per layer. The petal material fades its outermost edge, which anti-aliases the outline without multisampling.

How it's built

How to build a 3D card hover effect in Three.js

The cards use the Three.js WebGPURenderer and TSL, the Three.js Shading Language. TSL lets you write shaders as TypeScript functions that compile to WGSL for WebGPU and to GLSL for WebGL 2.

  1. 1. Describe the card shape with a distance field

    One small function knows how far any point is from the pill outline. The card edge, its anti-aliasing, the glass rim and every glow around it are derived from that single number.

    nodes.ts
    // Signed distance to the pill-shaped card, in card space.
    // Negative inside, zero on the outline, positive outside.
    function sdPill(p: Node<"vec2">) {
      const h = HH - HW
      return length(vec2(p.x, p.y.sub(clamp(p.y, -h, h)))).sub(HW)
    }
  2. 2. Resting glass and the lit iridescent face

    A resting card is smoked glass: black at the top, the element's tint pooling at the bottom, a hairline rim. When lit, four soft colour blobs drift over the face, gently warped by noise. The printed face is a canvas texture drawn once at start-up.

  3. 3. Effects as additive layers behind the card

    Each element adds a plane behind its card. The shader computes light only, and the planes are blended additively without touching the alpha channel, so the dark room shows through and the card stays on top.

    effects.ts
    // Flames: a gradient from the card outline outwards,
    // broken into tongues by three layers of rising noise.
    const reach = mix(0.05, 0.62, up.pow(1.25)).add(above.mul(0.95))
    const heat = clamp(
      float(1).sub(d.div(reach)).add(noise.mul(mix(0.35, 1.05, up))).sub(0.18),
      0.0, 1.0,
    )
  4. 4. Particles that cost no JavaScript

    Embers, sparks, rings and motes are instanced sprites. Each instance derives its position, size and fade from its index and the time inside the shader, so the CPU never updates a particle.

    effects.ts
    // Embers live entirely on the GPU: no per-frame JavaScript.
    const life = fract(time.mul(rnd(1).mul(0.35).add(0.28)).add(rnd(2)))
    material.positionNode = vec3(x0, float(HH - 0.25).add(life.mul(1.1)), 0.02)
    const embers = new THREE.Sprite(material)
    embers.count = 70 // one draw call, 70 instances
  5. 5. The room: reflection, bloom and grain

    A single post-processing pass paints the room behind the cards in the lit element's colour, mirrors the cards in the floor with a blur that grows with distance, adds bloom and a touch of film grain. Bloom is held back over the cards so their faces stay readable.

    ElementalCards.ts
    // WebGPU where available, WebGL 2 everywhere else.
    const renderer = new THREE.WebGPURenderer({ canvas, antialias: false })
    await renderer.init()
    renderer.backend.isWebGPUBackend // true on WebGPU

Interaction

Hover, click and scroll: interaction that reacts to you

Static cards are a picture. These respond to what you do, which is what keeps visitors on a landing page.

Cursor tilt and glare

The card under your cursor leans toward it in 3D. A soft glare slides over the glass and light catches the rim nearest to the pointer.

Effects that follow the cursor

Flames lean, sun rays gather, wind bends around the pointer and the lotus sways. A faint light in the element's colour follows the cursor through the room.

Click to ignite

Clicking the lit card sends out a ring in its colour, a burst of sparks and a short flare of its effect. Clicking a side card scrolls to its chapter.

Scroll-driven carousel

The section is pinned while you scroll. Scroll position moves the carousel continuously, so effects fade out as a card leaves the centre and build up as the next one arrives.

Performance

WebGPU performance: built to run at 120 fps

A beautiful effect that stutters looks broken. These are the decisions that keep the scene smooth on a laptop and usable on a phone.

  • The GPU does the work

    Shapes, effects, particles, reflection and bloom are all shaders. Per frame, JavaScript only updates a handful of numbers: carousel position, cursor and the lotus petal angles.

  • Noise from a texture

    Procedural 3D noise per pixel is expensive on large glow planes. One tiling 256 × 256 noise texture, generated once at start-up, replaces it with cheap texture reads.

  • No multisampling

    Every edge is anti-aliased inside its shader, so the half-float post-processing target does not need costly MSAA.

  • Adaptive resolution

    The engine measures frame times against the display's refresh rate. If frames keep arriving late, it lowers the pixel ratio step by step and raises it again when there is headroom.

  • Only render what is visible

    The engine loads when the section comes near, renders only while it is on screen and stops when the tab is hidden. The page text is server-rendered HTML and never waits for WebGL.

  • WebGPU first, WebGL 2 fallback

    The WebGPURenderer uses WebGPU where the browser supports it and falls back to WebGL 2 automatically. The same TSL code runs on both.

For your website

Interactive card effects for your landing page or product

The same building blocks work far beyond elements and lotus flowers. A few ideas where an interactive 3D card section pays off:

Pricing and plan cards

Make the recommended plan glow, react to the cursor and ignite on selection.

Product and feature cards

Give every feature its own visual effect that explains it at a glance.

Onboarding, quizzes and results

Reveal a personality type, a recommendation or a reward with a moment people remember.

Collectible and game cards

Rarity glows, foil effects and unlock animations for game UIs and fan communities.

SaaS and AI landing page heroes

A hero section visitors want to play with, without hurting load time or SEO.

Campaign and event pages

A scroll-driven story for a launch, a product drop or a conference.

I build it to your brief: your colours, your content, the number of cards and the effects you want, in plain Three.js or inside React and Next.js. You get clean, documented code and a section that works on phones too.

TypeScript, React & Next.js development

Questions about interactive 3D cards

Does this work in every browser?

It uses WebGPU in browsers that support it, such as current Chrome and Edge and recent Safari and Firefox versions on supported systems. Everywhere else the same code runs on WebGL 2. If neither is available, the section shows a still image and all text stays readable.

Does a WebGL section hurt SEO or page speed?

Not when it is built this way. All text is server-rendered HTML that search engines read directly. The 3D engine loads only when the section comes near, pauses when it is off screen, and a lightweight poster image shows until the first frame is ready.

Can I use effects like these in React or Next.js?

Yes. The engine is a framework-independent TypeScript class that a small client component mounts and disposes. This page itself is a Next.js page.

Can you adapt it to my brand and content?

Yes. Colours, number of cards, texts, icons, effects and the scroll story are all adjustable. I build exactly what your brief describes and agree any open design questions with you first.

What does a section like this cost?

I work at 75 USD per hour. The total depends on the number of cards and effects, the interactions and the integration into your site. We agree on scope and an estimate before I start.

What is TSL in Three.js?

TSL, the Three.js Shading Language, lets you write shaders as JavaScript or TypeScript functions. Three.js compiles them to WGSL for WebGPU or to GLSL for WebGL 2, so one shader runs on both.

Freelance · $75 USD / hour · Worldwide

Let's build something people want to play with.

Tell me what the section should do, where it will live and your timeline. I reply with questions or a first estimate. Writing in German is fine too.

Design inspiration: the elemental cards concept by Zsolt Kacso. This version was rebuilt from scratch with Three.js, WebGPU and TSL. Original post on X