I Built an Interactive 3D Tilt Card with Canvas Particles (No Libraries)
I wanted a small, self-contained demo for my dev profile that actually shows some interactive skill - not just another static card. So I built one combining three techniques, all in vanilla JS with zero dependencies:
- A canvas-based particle network background
- A glassmorphic card that tilts in 3D based on mouse position
- A typewriter effect cycling through role text
Here's how each piece works.
The particle network
The background is a <canvas> with ~70 particles drifting slowly across the screen. Each particle bounces off the edges, and any two particles within 120px of each other get a connecting line, with opacity fading based on distance:
if (dist < 120) {
ctx.strokeStyle = `rgba(91,140,255, ${1 - dist / 120})`;
ctx.beginPath();
ctx.moveTo(a.x, a.y);
ctx.lineTo(b.x, b.y);
ctx.stroke();
}
Nothing fancy - just requestAnimationFrame and basic distance checks - but it reads as a lot more polished than it is to build.
The 3D tilt effect
This is pure CSS transform: rotateX / rotateY, driven by mouse position:
document.addEventListener('mousemove', e => {
const rx = (e.clientY / window.innerHeight - 0.5) * -14;
const ry = (e.clientX / window.innerWidth - 0.5) * 14;
card.style.transform = `rotateX(${rx}deg) rotateY(${ry}deg)`;
});
The key CSS property making this look 3D (not just skewed) is transform-style: preserve-3d on the card, plus a perspective value on its parent container. Without perspective set on the parent, the rotation just looks flat and wrong.
The typewriter effect
A small state machine that types out a string, pauses, deletes it, and moves to the next one in a list - no library, just setTimeout and two counters (charIndex, roleIndex) tracking position and direction.
Why build this instead of just... not
Small interactive demos like this are genuinely useful to have on hand - for a portfolio, a personal site hero section, or just proving to yourself you understand the fundamentals (canvas rendering, CSS 3D transforms, animation timing) without pulling in GSAP or Three.js for something this simple.
Total size: one HTML file, ~60 lines of CSS, ~60 lines of JS. No dependencies.
I'm a full-stack developer based in Lagos, Nigeria, building products under the Easywise brand - you can see more of my work at easywise.com.ng.
Comments
No comments yet. Start the discussion.