Creating an Animated Wave Logo with React and Tailwind

A detailed walkthrough of creating a dynamic wave animation using SVG, React, and Tailwind CSS

Creating an Animated Wave Logo with React and Tailwind

Creating an Animated Wave Logo with React and Tailwind

Our logo consists of 20 vertical lines that pulse in sequence to create a wave effect. Let's break down how each part works:

The Basic Structure

First, we define our constants and types. These control the fundamental properties of our animation:

// Constants
const TOTAL_LINES = 20;
const LINE_HEIGHT_MIN = 16;
const LINE_HEIGHT_RANGE = 32;
const COLORS = [
  "stroke-pink-500",
  "stroke-purple-400",
  "stroke-yellow-500",
  "stroke-green-400",
  "stroke-blue-500",
] as const;

These constants define:

  • The number of lines in our wave (20)
  • The minimum height of each line (16px)
  • The random height range (up to additional 32px)
  • The color palette that cycles through our lines

Animation Classes

For the animation classes, we use explicit class names that Tailwind can detect at build time:

const animationClass =
  i === 0
    ? "animate-line-pulse-1"
    : i === 1
      ? "animate-line-pulse-2"
      // ... and so on

While this might look verbose, it ensures:

  • Tailwind correctly identifies all animation classes
  • The animations work reliably in production
  • Type safety is maintained
  • The build process can optimize effectively

The Animation Magic

The wave effect is powered by Tailwind's animation system. The magic happens in our configuration where we:

  1. Define a single keyframe animation for the pulse effect
  2. Generate variations of this animation with calculated delays
  3. Use TypeScript to ensure type safety throughout
// Animation configuration
const TOTAL_LINES = 20;
const ANIMATION_DURATION = 10; // seconds
const BASE_DELAY = 0.5; // seconds between each line
 
// Helper function to calculate delay for each line
const calculateDelay = (lineNumber: number): number => {
  if (lineNumber === 1) return 0;
  return -((TOTAL_LINES - lineNumber + 1) * BASE_DELAY);
};

The delay calculation is crucial:

  • First line has no delay (starts immediately)
  • Each subsequent line's delay is calculated relative to the total animation
  • Negative delays create the illusion of a continuous wave

The Keyframe Definition

Each line starts and ends at 25% opacity. It peaks at 100% opacity between 5-10% of its animation cycle. The gradual fade creates a smooth pulse effect.

The Animation Generator

Creates 20 different animations, one for each line. Each animation takes 10 seconds to complete, runs infinitely, and has a specific delay based on its position.

The delay formula creates the sequential effect:

  • First line starts immediately
  • Each subsequent line starts 0.5s after the previous one
  • Creates a smooth wave motion from left to right

Putting It All Together

The logo is used in the site header with overlaid text:

<div className="relative flex items-center">
  <Icons.logo className="h-16 w-[256px]" />
  <span className="absolute left-[72px] text-3xl font-extrabold tracking-tight">
    subaud
  </span>
</div>

Key Learnings

  • Animation Timing - Negative delays create a smooth sequential animation effect.
  • SVG Optimization - Using individual SVGs for each line gives us more control over animations.

Conclusion

This technique demonstrates how to create complex animations using simple building blocks. By combining SVG, React's component model, and Tailwind's animation system, we can create engaging visual effects with maintainable, type-safe code.