Skip to main content

Animation System Overview

Your portfolio uses two animation systems:
  1. Tailwind CSS Animations - Keyframe animations for glassmorphism effects and micro-interactions
  2. Scroll Animations - Custom React components using IntersectionObserver for scroll-triggered animations

Tailwind CSS Animations

Built-in Animations

The portfolio includes 11 custom animations defined in tailwind.config.js:
animation: {
  'glass-shimmer': 'glass-shimmer 2s ease-in-out infinite alternate',
  'glow-pulse': 'glow-pulse 4s ease-in-out infinite',
}

Animation Keyframes

Each animation has corresponding keyframes:

Glass Shimmer

tailwind.config.js
'glass-shimmer': {
  '0%': { 'background-position': '-200% 0' },
  '100%': { 'background-position': '200% 0' },
}
Use with gradient backgrounds for a shimmer effect:
<div className="glass-shimmer animate-glass-shimmer">
  Content here
</div>

Float Animation

tailwind.config.js
'float': {
  '0%, 100%': { transform: 'translateY(0px) rotate(0deg)' },
  '50%': { transform: 'translateY(-20px) rotate(5deg)' },
}
Creates a gentle floating effect with slight rotation:
<div className="animate-float">
  Floating element
</div>
Use animate-float-delayed for staggered floating effects on multiple elements.

Chat Button Animations

Special animations for the chat button:
'chat-pulse': {
  '0%, 100%': { transform: 'scale(1)', opacity: '1' },
  '50%': { transform: 'scale(1.05)', opacity: '0.9' },
}

Gradient Shift

tailwind.config.js
'gradient-shift': {
  '0%, 100%': { 'background-position': '0% 50%' },
  '50%': { 'background-position': '100% 50%' },
}
Animates gradient backgrounds. Use with background-size: 200%:
<div className="bg-gradient-to-r from-purple-500 to-blue-500 
                bg-[length:200%_200%] animate-gradient-shift">
  Animated gradient
</div>

Scroll Animations

Custom React components for scroll-triggered animations in src/components/scroll-animations.tsx.

ScrollFadeIn Component

Fades in and slides up when scrolling into view:
src/components/scroll-animations.tsx
export function ScrollFadeIn({ 
  children, 
  className = "", 
  delay = 0 
}: ScrollAnimationProps) {
  // Implementation uses IntersectionObserver
  // Adds 'animate-fade-in-up' class when in viewport
}

Usage

import { ScrollFadeIn } from './components/scroll-animations'

<ScrollFadeIn delay={100}>
  <h2>This will fade in</h2>
</ScrollFadeIn>
The delay prop is in milliseconds and allows you to stagger multiple animations.

ScrollSlideIn Component

Slides in from the left when scrolling into view:
src/components/scroll-animations.tsx
export function ScrollSlideIn({ 
  children, 
  className = "", 
  delay = 0 
}: ScrollAnimationProps) {
  // Adds 'animate-slide-in-left' class when in viewport
}

Usage

import { ScrollSlideIn } from './components/scroll-animations'

<ScrollSlideIn delay={200}>
  <div>This will slide in from left</div>
</ScrollSlideIn>

How Scroll Animations Work

1

Initial State

Elements start with opacity-0 and transform classes:
className="opacity-0 translate-y-8 transition-all duration-700 ease-out"
2

Viewport Detection

IntersectionObserver watches for element entering viewport:
const observer = new IntersectionObserver(
  (entries) => { /* ... */ },
  { threshold: 0.1 }
)
3

Animation Trigger

When visible, opacity and transform classes are removed with optional delay:
setTimeout(() => {
  target.classList.add(animationClass)
  hiddenClasses.forEach((c) => target.classList.remove(c))
}, delay)
Scroll animations trigger once when the element enters the viewport. They don’t reverse when scrolling back up.

Creating Custom Animations

Adding Tailwind Animations

1

Define Keyframes

Add your keyframes in tailwind.config.js:
keyframes: {
  'my-animation': {
    '0%': { opacity: '0', transform: 'scale(0.8)' },
    '100%': { opacity: '1', transform: 'scale(1)' },
  }
}
2

Register Animation

Add the animation configuration:
animation: {
  'my-animation': 'my-animation 0.5s ease-out',
}
3

Use in Components

Apply with the animate- prefix:
<div className="animate-my-animation">
  Animated content
</div>

Creating New Scroll Animation Components

Extend the existing pattern in scroll-animations.tsx:
src/components/scroll-animations.tsx
export function ScrollZoomIn({ 
  children, 
  className = "", 
  delay = 0 
}: ScrollAnimationProps) {
  const elementRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    const element = elementRef.current
    if (!element) return

    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            setTimeout(() => {
              element.classList.remove('opacity-0', 'scale-75')
              element.classList.add('opacity-100', 'scale-100')
            }, delay)
          }
        })
      },
      { threshold: 0.1 }
    )

    observer.observe(element)
    return () => observer.disconnect()
  }, [delay])

  return (
    <div 
      ref={elementRef} 
      className={`opacity-0 scale-75 transition-all duration-700 ease-out ${className}`}
    >
      {children}
    </div>
  )
}

Performance Optimization

GPU Acceleration

The portfolio includes GPU acceleration utilities:
src/index.css
.transform-gpu {
  backface-visibility: hidden;
  transform-style: preserve-3d;
  -webkit-backface-visibility: hidden;
  -webkit-transform-style: preserve-3d;
}
Add this class to animated elements for better performance:
<div className="animate-float transform-gpu">
  GPU-accelerated animation
</div>
Use GPU acceleration for animations involving transforms, but avoid overuse as it increases memory usage.

Animation Best Practices

  1. Use will-change sparingly - Only on actively animating elements
  2. Prefer transforms - Use transform over position changes
  3. Reduce motion - Respect user preferences with prefers-reduced-motion
  4. Stagger animations - Use delay props to avoid overwhelming users

Animation Timing Reference

DurationUse CaseExample
0.2sQuick transitionsButton hover, fade-scale
0.5-1sUI transitionsModal open/close
2-3sAmbient effectsShimmer, pulse
4-6sDecorativeFloat, glow-pulse
All animations use ease-in-out or ease-out timing functions for smooth, natural motion.

Build docs developers (and LLMs) love