heroes /
Video Background Hero
Full-width cinematic hero with an animated gradient background that mimics a video. White text, centered headline, and a scroll indicator.
Preview
Source
tsx
"use client";
import { motion } from "framer-motion";
import { ArrowRight, Play } from "lucide-react";
import { Button } from "@/components/ui/button";
export default function VideoBgHero() {
return (
<section className="relative min-h-screen flex items-center justify-center overflow-hidden">
{/* Cinematic animated gradient — replace this div with a <video> tag for production */}
<div className="absolute inset-0 z-0">
<div
className="absolute inset-0"
style={{
background:
"linear-gradient(135deg, #0f0c29, #302b63, #24243e)",
animation: "cinematicShift 12s ease-in-out infinite alternate",
}}
/>
<div
className="absolute inset-0 opacity-50"
style={{
background:
"radial-gradient(ellipse at 20% 50%, rgba(120, 40, 200, 0.5) 0%, transparent 60%), radial-gradient(ellipse at 80% 20%, rgba(20, 100, 220, 0.4) 0%, transparent 50%), radial-gradient(ellipse at 60% 80%, rgba(200, 50, 80, 0.3) 0%, transparent 50%)",
animation: "cinematicGlow 8s ease-in-out infinite alternate",
}}
/>
{/* Vignette overlay */}
<div className="absolute inset-0 bg-gradient-to-b from-black/40 via-transparent to-black/70" />
</div>
{/* Keyframe styles injected via a style tag */}
<style>{`
@keyframes cinematicShift {
0% { filter: brightness(0.9) saturate(1.2); }
50% { filter: brightness(1.1) saturate(1.5); }
100% { filter: brightness(0.85) saturate(1.3); }
}
@keyframes cinematicGlow {
0% { opacity: 0.4; transform: scale(1); }
50% { opacity: 0.65; transform: scale(1.05); }
100% { opacity: 0.5; transform: scale(1.02); }
}
`}</style>
{/* 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.8, ease: "easeOut" }}
className="flex flex-col items-center gap-6"
>
<span className="inline-flex items-center gap-2 text-xs font-semibold uppercase tracking-widest text-white/70 border border-white/20 rounded-full px-4 py-2 backdrop-blur-sm">
Award-winning design studio
</span>
<h1 className="text-5xl sm:text-6xl lg:text-7xl font-extrabold tracking-tight text-white leading-[1.05]">
We craft experiences
<br />
that{" "}
<span className="italic text-transparent bg-clip-text bg-gradient-to-r from-rose-300 to-violet-300">
move people
</span>
</h1>
<p className="text-lg sm:text-xl text-white/70 max-w-xl leading-relaxed">
From concept to launch, we build digital products that captivate
audiences and drive measurable results for ambitious brands.
</p>
<div className="flex flex-col sm:flex-row items-center gap-3 pt-2">
<Button
size="lg"
className="gap-2 text-base bg-white text-black hover:bg-white/90 min-w-[180px]"
>
Start your project
<ArrowRight className="w-4 h-4" />
</Button>
<Button
size="lg"
variant="outline"
className="gap-2 text-base border-white/30 text-white hover:bg-white/10 hover:text-white min-w-[180px]"
>
<Play className="w-4 h-4 fill-current" />
Watch reel
</Button>
</div>
</motion.div>
</div>
{/* Bottom scroll indicator */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 1.2, duration: 0.8 }}
className="absolute bottom-8 left-1/2 -translate-x-1/2 flex flex-col items-center gap-2"
>
<span className="text-xs text-white/40 uppercase tracking-widest">Scroll</span>
<motion.div
animate={{ y: [0, 8, 0] }}
transition={{ duration: 1.5, repeat: Infinity, ease: "easeInOut" }}
className="w-0.5 h-8 bg-gradient-to-b from-white/40 to-transparent rounded-full"
/>
</motion.div>
</section>
);
} Claude Code Instructions
CLI Install
npx innovations add video-bgWhere to use it
Place this as a full-bleed hero at the very top of your page (no navbar padding needed — the hero provides its own space).
In Astro (src/pages/index.astro):
import VideoBgHero from '../components/innovations/heroes/video-bg';
<VideoBgHero client:load />
In Next.js (app/page.tsx):
import VideoBgHero from '@/components/innovations/heroes/video-bg';
To use a real video instead of the animated gradient:
1. Remove the animated gradient divs inside the "absolute inset-0 z-0" container
2. Replace with:
<video
autoPlay muted loop playsInline
className="absolute inset-0 w-full h-full object-cover"
src="/your-video.mp4"
/>
3. Keep the vignette overlay div for readability
Keep the vignette overlay (bg-gradient-to-b from-black/40) — it ensures text is readable over any video content.