Back to Dictionary
Waiting & Loading
●○○Ready to Use
Recommended defaultBuffering Animation
Often an overlapping circle array or a dotted spinner indicating that a media stream has paused to download more data.
Use
Video players
Avoid
Standard API data fetching
Safer Alternative
No safer default listed.
Risk Level
Low risk
Live Demo
What It Is
Often an overlapping circle array or a dotted spinner indicating that a media stream has paused to download more data.
✓When to Use
- Video players
- Audio players
- Live streams
✕When NOT to Use
- Standard API data fetching
Configuration Tips
- 01Keep it slightly translucent so it doesn't completely block the paused frame of the video
You've Seen It In
YouTubeNetflixSpotify
AI Implementation Prompts
Move from a fast scaffold to production details, then tune timing and edge states.
Create a buffering spinner like YouTube's.
Reference Implementation
The same implementation approach used by the live preview, kept compact enough to inspect and adapt.
"use client";
import { motion } from 'framer-motion';
export function BufferingAnimationDemo({ isPlaying = false }: { isPlaying?: boolean }) {
return (
<div className="flex h-64 w-full items-center justify-center overflow-hidden rounded-2xl bg-stone-900 p-4 shadow-sm ring-1 ring-stone-900">
{"text-stone-400 italic">/* Simulating a video player background */}
<div className="relative w-full h-full rounded-xl bg-stone-800 flex items-center justify-center overflow-hidden shadow-inner">
<div
aria-hidden="true"
className="absolute inset-0 bg-cover bg-center opacity-40 mix-blend-overlay"
style={{
backgroundImage: "url('https:">//images.unsplash.com/photo-1536440136628-849c177e76a1?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&q=80')"
}}
/>
<div className="absolute inset-0 bg-gradient-to-t from-stone-900/80 to-transparent" />
{isPlaying && (
<motion.div
className="relative w-12 h-12 flex items-center justify-center"
animate={{ rotate: 360 }}
transition={{ duration: 1.5, repeat: Infinity, ease: "linear" }}
>
{Array.from({ length: 8 }).map((_, i) => (
<motion.span
key={i}
className="absolute top-0 w-2.5 h-2.5 bg-white rounded-full bg-opacity-80 shadow-[0_0_10px_rgba(255,255,255,0.5)]"
style={{
originY: "24px", "text-stone-400 italic">// Half of the 48px wrapper
rotate: i * 45,
}}
animate={{ opacity: [0.2, 1, 0.2] }}
transition={{
duration: 1.5,
repeat: Infinity,
delay: (i * 1.5) / 8,
ease: "linear"
}}
/>
))}
</motion.div>
)}
<div className="absolute bottom-4 left-6 flex items-center gap-4 w-full pr-12">
<div className="w-8 h-8 rounded-full bg-white/10 flex items-center justify-center backdrop-blur-md">
<div className="w-0 h-0 border-t-4 border-t-transparent border-l-6 border-l-white border-b-4 border-b-transparent ml-1" />
</div>
<div className="flex-1 h-1 bg-white/20 rounded-full">
<div className="w-1/3 h-full bg-red-500 rounded-full" />
</div>
</div>
</div>
</div>
);
}