Skip to main content

Enhanced Animated Refresh Button – Free CSS JavaScript Spinner & Ring Glow UI Component (Glassmorphism, Hover Scale, Simulated Progress)

The Enhanced Animated Refresh Button is a free, copy-paste ready circular UI button component built with pure HTML, CSS custom keyframes, and vanilla JavaScript. It is designed as a production-ready loading state button — drop it into any project as a visual refresh or reload trigger with a full animation lifecycle. The button is a 90×90px circle with glassmorphism: background: rgba(255,255,255,0.05), border: 2px solid rgba(255,255,255,0.15), backdrop-filter: blur(14px), box-shadow: 0 10px 30px rgba(0,0,0,0.55). The background uses a triple radial-gradient layer: purple glow at 20%/20%, cyan glow at 80%/80%, over --bg: #0f172a deep navy.

Hover state: transform: scale(1.2) rotate(-5deg) — the button scales up 20% and tilts 5 degrees counter-clockwise. box-shadow: 0 0 35px 8px rgba(124,58,237,0.8) adds an 8px spread purple glow that extends well beyond the button boundary. The SVG refresh icon strokes to #06b6d4 (cyan) and rotates 30 degrees with scale(1.15). Click state: the SVG icon is hidden (display:none), the spinner is shown — 70×70px, border: 5px solid rgba(255,255,255,0.2), border-top-color: #06b6d4, spinning via @keyframes spin at 0.9s linear infinite. Simultaneously the ring becomes visible (opacity 0→1) — 100×100px, border-top-color: #7c3aed (purple), border-right-color: #ec4899 (pink), rotating at 1.2s linear (slower than the inner spinner, creating a layered parallax). A simulated progress loop fires progress += 15 + Math.random() * 20 every 120ms until ≥100, then restores the icon.

What's Included in the Download

How to Replace the Simulated Progress with a Real API Call

The simulated simulate() function is a placeholder for any real async operation. Replace it with your actual fetch/axios call: btn.classList.add('active'); icon.style.display='none'; spinner.style.display='block'; at the start, then in your .then() or after your await: spinner.style.display='none'; icon.style.display='block'; btn.classList.remove('active');. The button animation system is entirely driven by the .active class — add it to start, remove it to stop. The spinner and ring CSS are already set up to respond to that single class toggle.

Why Two Rings Spin at Different Speeds

The inner spinner (70px, 0.9s) and outer ring (100px, 1.2s) intentionally rotate at different speeds. Because 1.2/0.9 = 4/3, they synchronize every 3.6 seconds (LCM of 0.9 and 1.2). Between sync points they create a continuously shifting angular relationship — the dual-color ring appears to orbit around the spinner rather than tracking with it. This creates visual depth and movement complexity from just two simple @keyframes spin → rotate(360deg) animations.

License

Released under Creative Commons Attribution 4.0 International (CC BY 4.0). Free for personal and commercial use with attribution to Coodeverse.

Source Code

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Enhanced Animated Refresh Button</title>
</head>
<body>
<div class="refresh-btn" id="refreshBtn">
  <svg id="refreshIcon" viewBox="0 0 24 24" fill="none" stroke="currentColor">
    <path d="M4.93 4.93a10 10 0 0114.14 0l1.41-1.41"/>
    <path d="M20.07 19.07a10 10 0 01-14.14 0l-1.41 1.41"/>
  </svg>
  <div class="spinner" id="spinner"></div>
  <div class="ring" id="ring"></div>
</div>
</body>
</html>

Frequently Asked Questions

Common questions about the free Enhanced Animated Refresh Button project.

Yes — 100% free under Creative Commons Attribution 4.0. No sign-up, no payment. Click Download Project and use it as a loading state button component in any project with attribution to Coodeverse.

Set equal width/height with border-radius:50% for a circle. Then: background:rgba(255,255,255,0.05) (near-transparent fill), border:2px solid rgba(255,255,255,0.15) (subtle white border), backdrop-filter:blur(14px) (frosted glass blur of background), box-shadow:0 10px 30px rgba(0,0,0,0.55) (depth shadow). Add overflow:hidden to contain child elements (spinner, ring) within the circle boundary.

Use box-shadow with spread radius: .refresh-btn:hover { box-shadow: 0 0 35px 8px rgba(124,58,237,0.8); }. The syntax: 0 x-offset, 0 y-offset, 35px blur, 8px spread (extends 8px beyond the element in all directions), rgba(124,58,237,0.8) purple at 80% opacity. Combine with transform:scale(1.2) rotate(-5deg) and transition:0.3s ease for a simultaneous scale + tilt + glow hover effect.

Create a circle div: border:5px solid rgba(255,255,255,0.2); border-top-color:#06b6d4; border-radius:50%. One colored border-top creates a spinning arc. Animate: @keyframes spin { to { transform:rotate(360deg); } } applied as animation:spin 0.9s linear infinite. Use display:none by default and toggle to display:block on click. Position absolute inside the button (relative parent) to layer over the SVG icon.

Create a div slightly larger than the button (100px for a 90px button): border:3px solid transparent; border-top-color:#7c3aed; border-right-color:#ec4899; border-radius:50%. Spin at a different speed: animation:ringSpin 1.2s linear infinite. Control via opacity:0 default → opacity:1 when parent has .active class. The two-speed difference (0.9s inner vs 1.2s ring) creates continuous angular shift — the ring appears to orbit the spinner rather than track with it.

Use recursive setTimeout: let progress = 0; function simulate() { progress += 15 + Math.random() * 20; if (progress < 100) { setTimeout(simulate, 120); } else { /* complete */ } } simulate(). Each call advances 15–35 at random and schedules the next at 120ms. The randomness makes loading feel natural. On completion, reverse all state: hide spinner, show icon, remove .active class. Replace simulate() with your real fetch/.then() for production use.

Browse coodeverse.com/projects — Cute Lamp Character (CSS keyframe character), Gold Ace Poker Cards (SVG filters), Modern Neon Clock, NEXUS 3D CSS Cubes, VORTEX Canvas, and more. All 100% free with complete HTML CSS JavaScript source code.