heroes /
Animated Blob Hero
Vibrant hero with multiple morphing CSS blob shapes animating in the background. Centered text with framer-motion entrance.
Preview
Source
tsx
"use client";
import { motion } from "framer-motion";
import { ArrowRight, Star } from "lucide-react";
import { Button } from "@/components/ui/button";
const blobs = [
{
className: "top-[-10%] left-[-5%] w-[500px] h-[500px]",
gradient: "from-violet-500 via-purple-400 to-fuchsia-500",
duration: 10,
delay: 0,
},
{
className: "bottom-[-15%] right-[-10%] w-[600px] h-[600px]",
gradient: "from-sky-400 via-cyan-400 to-teal-400",
duration: 12,
delay: 2,
},
{
className: "top-[30%] right-[10%] w-[350px] h-[350px]",
gradient: "from-rose-400 via-pink-400 to-fuchsia-400",
duration: 9,
delay: 1,
},
];
const morphKeyframes = [
"60% 40% 30% 70% / 60% 30% 70% 40%",
"30% 60% 70% 40% / 50% 60% 30% 60%",
"50% 50% 40% 60% / 40% 70% 60% 50%",
"70% 30% 50% 50% / 30% 60% 40% 70%",
"60% 40% 30% 70% / 60% 30% 70% 40%",
];
export default function AnimatedBlobHero() {
return (
<section className="relative min-h-screen flex items-center justify-center overflow-hidden bg-background">
{/* Blobs */}
{blobs.map((blob, i) => (
<motion.div
key={i}
className={`absolute ${blob.className} bg-gradient-to-br ${blob.gradient} opacity-20 blur-3xl`}
animate={{ borderRadius: morphKeyframes }}
transition={{
duration: blob.duration,
repeat: Infinity,
ease: "easeInOut",
delay: blob.delay,
}}
/>
))}
{/* Sharp inner blobs (less blur, more vivid) */}
<motion.div
className="absolute top-[15%] left-[20%] w-48 h-48 bg-gradient-to-br from-primary to-violet-600 opacity-30 blur-xl"
animate={{ borderRadius: morphKeyframes, scale: [1, 1.1, 0.95, 1.05, 1] }}
transition={{ duration: 7, repeat: Infinity, ease: "easeInOut" }}
/>
<motion.div
className="absolute bottom-[20%] right-[25%] w-32 h-32 bg-gradient-to-br from-cyan-400 to-sky-600 opacity-40 blur-lg"
animate={{ borderRadius: morphKeyframes, scale: [1, 0.9, 1.1, 0.95, 1] }}
transition={{ duration: 5, repeat: Infinity, ease: "easeInOut", delay: 1.5 }}
/>
{/* Content */}
<div className="relative z-10 container mx-auto px-6 text-center max-w-3xl">
<motion.div
initial={{ opacity: 0, y: 40 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.7, ease: "easeOut" }}
className="flex flex-col items-center gap-6"
>
{/* Rating badge */}
<motion.div
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.4, delay: 0.15 }}
className="inline-flex items-center gap-1.5 bg-card border border-border rounded-full px-4 py-2 shadow-sm"
>
{[1, 2, 3, 4, 5].map((s) => (
<Star key={s} className="w-3.5 h-3.5 fill-amber-400 text-amber-400" />
))}
<span className="text-xs font-semibold text-foreground ml-1">
Rated 4.9 by 3,000+ users
</span>
</motion.div>
<motion.h1
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.65, delay: 0.2 }}
className="text-5xl sm:text-6xl lg:text-7xl font-extrabold tracking-tight text-foreground leading-[1.05]"
>
Design without{" "}
<span className="relative inline-block">
<span className="relative z-10 bg-gradient-to-r from-violet-500 via-fuchsia-500 to-rose-500 bg-clip-text text-transparent">
limits
</span>
</span>
</motion.h1>
<motion.p
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.65, delay: 0.3 }}
className="text-lg sm:text-xl text-muted-foreground max-w-xl leading-relaxed"
>
A creative workspace that adapts to you — expressive, intuitive, and
powerful enough for professionals who refuse to compromise.
</motion.p>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.65, delay: 0.4 }}
className="flex flex-col sm:flex-row items-center gap-3 pt-2"
>
<Button size="lg" className="gap-2 text-base">
Try it free
<ArrowRight className="w-4 h-4" />
</Button>
<Button size="lg" variant="ghost" className="text-base">
Explore gallery
</Button>
</motion.div>
</motion.div>
</div>
</section>
);
} Claude Code Instructions
CLI Install
npx innovations add animated-blobWhere to use it
Place as the first section after the navbar on your landing page.
In Astro (src/pages/index.astro):
import AnimatedBlobHero from '../components/innovations/heroes/animated-blob';
<AnimatedBlobHero client:load />
In Next.js (app/page.tsx):
import AnimatedBlobHero from '@/components/innovations/heroes/animated-blob';
// Add at the top of the page return
Blob colors are controlled via Tailwind gradient classes in the blobs array at the top of the component. Edit 'from-', 'via-', and 'to-' classes to match your brand palette. The blur-3xl class controls softness — reduce to blur-2xl for sharper blobs.