Built with Webflow

From Webflow to WebGL: Lenticular Motion Experiment

Franco Beltramella

🎨 Showcase — “Lenticular Cards”

Initial Context

Inspiration:
This project was born from a usual creative ritual  exploring visuals that spark curiosity. Among those images on Pinterest, I came across a sequence that looked like a painting almost tactile, with that nostalgic feeling of physical art. It immediately reminded me of the lenticular cards that used to come inside snack packages those cards that changed images when you moved them.
That blend of analog nostalgia and digital expression became the starting point.
One of the things I enjoy most about my showcases is that the things I create aren’t extremely complex they’re simple ideas, but I like the idea of taking them a bit deeper, turning them into a kind of digitalized art form.
That mindset makes me truly enjoy the process and gives me complete creative freedom.

Showcase Goals

The goal wasn’t to create something complex, but rather to turn a simple idea into a digital art piece. I wanted to explore:

How to bring the physical texture of a nostalgic object into a web environment.
How to integrate Three.js and custom shaders within Webflow without relying on external libraries.
How to transform a simple interaction (like hover or mouse movement) into something that evokes emotion and curiosity.
Behind the Scenes 
The entire scene runs on Three.js, where two textures blend together based on mouse movement.
The logic is handled through a uniform variable u_mix, which determines how much of each texture is visible.
this.material = new THREE.ShaderMaterial({
uniforms: {
u_mix: { value: 0 },
u_texture1: { value: tex1 },
u_texture2: { value: tex2 },
u_time: { value: 0 },
u_dust: { value: 0 },
},
fragmentShader: `
uniform sampler2D u_texture1;
uniform sampler2D u_texture2;
uniform float u_mix;
varying vec2 vUv;

void main() {
vec4 t1 = texture2D(u_texture1, vUv);
vec4 t2 = texture2D(u_texture2, vUv);
gl_FragColor = mix(t2, t1, u_mix);
}
`
});

From there, mouse movement dynamically updates the mix and rotation of the card:
this.container.addEventListener("mousemove", (e) => {
const rect = this.container.getBoundingClientRect();
const x = (e.clientX - rect.left) / rect.width;
const y = (e.clientY - rect.top) / rect.height;

this.targetRotationY = (x * 2 - 1) * 0.3;
this.targetRotationX = -(y * 2 - 1) * 0.15;
this.targetMix = (x + 1.0) / 2.0;
});

This simple piece of logic gives life to the effect the card subtly follows your mouse while its surface “flips” between two images, just like the lenticular cards from the 2000s.

✨ Adding Magic — Dust & Vintage Look

​​​​​​To give the experience more soul, I added a subtle shader layer simulating dust particles and vintage film grain, inspired by warm tones like #fff8c7.
float dustNoise(vec2 uv, float time) {
float n = random(uv * 20.0 + time * 0.5);
n += random(uv * 40.0 - time * 0.8) * 0.5;
return smoothstep(0.4, 0.8, n);
}

void main() {
vec4 color = mix(texture2D(u_texture1, vUv), texture2D(u_texture2, vUv), u_mix);
float dust = dustNoise(vUv, u_time);
vec3 dustColor = vec3(1.0, 0.972, 0.78);
color.rgb = mix(color.rgb, dustColor, u_dust * dust);
gl_FragColor = color;
}

Then, I used GSAP to create a cinematic transition when switching between images:
tl.to(card.material.uniforms.u_dust, { value: 1, duration: 0.4 })
.to(card.material.uniforms.u_mix, { value: 0, duration: 0.3 }, "<")
.add(() => card.updateTextures(img1, img2))
.to(card.material.uniforms.u_dust, { value: 0, duration: 1.2 });

The dust rises and fades, revealing the new image like blowing time off an old photograph.

đź’­ Reflection

One of the things I love about my showcases is that they’re not built around complexity — they’re built around intention. This project isn’t about heavy 3D or complex math. It’s about emotion through movement.
Simple ideas, deeply crafted.
Looking to bring something artistic and interactive to your next project?
Let’s create something unforgettable together. → Work with me
Other Showcases
Like this project

Posted Oct 7, 2025

Created a digital art piece using Three.js and Webflow, inspired by lenticular cards.

Join 50k+ companies and 1M+ independents

Contra Logo

© 2025 Contra.Work Inc