DEV Community

Fahad Ali Khan
Fahad Ali Khan

Posted on

Building an Animated Portfolio Hero with GSAP, SplitText, and a Canvas Particle Background

Modern portfolio sites aren’t just about listing projects anymore. They’re an opportunity to demonstrate polish, motion design, and engineering decisions — all in one place.

Recently, I built an animated hero section that combines:

  • Character-by-character text reveal using GSAP SplitText
  • Liquid morph social icons with hover physics
  • A canvas particle background reacting to cursor movement
  • Responsive layout that works across devices

This article walks through the architecture, animation patterns, and lessons learned — so you can build something similar without fighting your layout or performance.

Here is the final Product: https://fahadalikhan.vercel.app/


The goal

I wanted a hero section that feels alive without being distracting:

  • Headline text animates in smoothly
  • Social icons pop into view and morph on hover
  • A particle field subtly reacts to cursor movement
  • Everything stays responsive and performant

The key was orchestrating multiple animation layers without turning the component into chaos.


Layer 1 — Character-by-character text animation

GSAP’s SplitText plugin makes it trivial to animate individual characters. Instead of animating the entire headline block, we split it into spans and animate each char with a stagger.

const split = new SplitText(TextRef.current, { type: "chars" });

timeline.from(split.chars, {
  opacity: 0,
  x: 50,
  duration: 0.9,
  stagger: 0.05,
  ease: "power3.out",
});
Enter fullscreen mode Exit fullscreen mode

This produces a cinematic reveal:

  • Characters slide in
  • Opacity fades up
  • Timing feels intentional

Important cleanup:

split.revert();
Enter fullscreen mode Exit fullscreen mode

Without this, repeated renders stack nested spans and break your DOM.


Layer 2 — Social icons with liquid morph hover

Instead of static icons, I wanted something tactile. The trick is animating:

  • scale
  • rotation
  • border-radius

Border-radius is what creates the organic “blob” shape.

Hover enter:

gsap.to(icon, {
  scale: 1.2,
  rotation: 180,
  borderRadius: "30% 70% 70% 30% / 30% 30% 70% 70%",
  ease: "elastic.out(1, 0.3)",
});
Enter fullscreen mode Exit fullscreen mode

Hover exit:

gsap.to(icon, {
  scale: 1,
  rotation: 0,
  borderRadius: "50%",
});
Enter fullscreen mode Exit fullscreen mode

The elastic easing gives the impression of physical bounce instead of mechanical motion.


Layer 3 — Entrance timeline orchestration

One common mistake is running separate animations independently. Instead, everything is sequenced on a GSAP timeline:

const tl = gsap.timeline();

tl.from(textChars, {...})
  .from(iconLinks, {...}, "-=0.3");
Enter fullscreen mode Exit fullscreen mode

This gives:

  • predictable timing
  • overlap control
  • easier debugging

You get a cohesive entrance instead of disconnected animations firing randomly.


Layer 4 — Canvas particle background

The particle system runs in a <canvas> behind the hero content:

  • particles arranged in a grid
  • mouse proximity drives wave distortion
  • rotation aligns particles toward the cursor

The canvas is positioned absolutely with a negative z-index:

canvas {
  position: absolute;
  inset: 0;
  z-index: -1;
}
Enter fullscreen mode Exit fullscreen mode

Key performance notes:

  • Use requestAnimationFrame
  • Reuse particle objects
  • Avoid layout reads inside the loop

This keeps animation smooth even on mid-range devices.


Responsiveness challenges

Animation-heavy layouts often break at medium breakpoints. A few practical fixes:

  • Constrain large media with max-width
  • Maintain aspect ratios with Tailwind utilities
  • Avoid fixed heights where possible

Example:

md:max-w-[450px]
aspect-[4/3]
mx-auto
Enter fullscreen mode Exit fullscreen mode

This prevents oversized visuals while preserving composition.


UX lessons learned

Motion should guide attention

Animations should reinforce hierarchy, not steal focus.

Physics > gimmicks

Elastic easing feels natural. Linear motion feels robotic.

Cleanup matters

Event listeners and SplitText wrappers must be reverted to avoid bugs.

Performance first

Canvas and GSAP can coexist — but avoid unnecessary recalculations.


Final thoughts

This hero section isn’t about flashy animation. It’s about layering:

  • typography motion
  • interactive affordances
  • subtle background energy

Together they create a polished first impression while staying performant and maintainable.

If you’re building a portfolio, landing page, or interactive UI, these techniques scale surprisingly well — and GSAP makes complex motion approachable once you understand timelines and sequencing.

Happy building.

Top comments (0)