interactive
intermediate
buttons
animation
hover
effects
components
ui
Category · Interactive Difficulty Level · Intermediate Published on · January 15, 2024

Animated Button Components

A comprehensive collection of modern animated buttons with various styles, effects, and interactive features for enhanced user experience

#buttons #animation #hover #effects #components #ui

Responsive Design

Yes

Dark Mode Support

No

lines

78

Browser Compatibility

No

Live Preview

Interact with the component without leaving the page.

700px

Animated Button Components

A comprehensive collection of modern animated buttons featuring various styles, hover effects, loading states, and interactive animations to enhance user experience and interface engagement.

Features

  • Multiple Button Styles: Primary, secondary, outline, ghost, and gradient buttons
  • Smooth Animations: CSS-based transitions with customizable timing
  • Hover Effects: Scale, glow, ripple, and morphing animations
  • Loading States: Spinner, progress, and pulse loading indicators
  • Icon Integration: Support for icons with smooth transitions
  • Responsive Design: Adapts to all screen sizes and touch devices
  • Accessibility Support: ARIA attributes and keyboard navigation
  • Modern Design: Clean aesthetics with subtle shadow effects

Demo

<div class="button-demo-container">
  
  <div class="button-section">
    <h3>Basic Button Styles</h3>
    <div class="button-grid">
      <button class="btn btn-primary">
        <span class="btn-text">Primary Button</span>
      </button>
      
      <button class="btn btn-secondary">
        <span class="btn-text">Secondary Button</span>
      </button>
      
      <button class="btn btn-outline">
        <span class="btn-text">Outline Button</span>
      </button>
      
      <button class="btn btn-ghost">
        <span class="btn-text">Ghost Button</span>
      </button>
      
      <button class="btn btn-gradient">
        <span class="btn-text">Gradient Button</span>
      </button>
      
      <button class="btn btn-danger">
        <span class="btn-text">Danger Button</span>
      </button>
    </div>
  </div>

  
  <div class="button-section">
    <h3>Animated Effects</h3>
    <div class="button-grid">
      <button class="btn btn-primary btn-scale">
        <span class="btn-text">Scale Effect</span>
      </button>
      
      <button class="btn btn-primary btn-glow">
        <span class="btn-text">Glow Effect</span>
      </button>
      
      <button class="btn btn-primary btn-ripple">
        <span class="btn-text">Ripple Effect</span>
        <span class="btn-ripple"></span>
      </button>
      
      <button class="btn btn-primary btn-slide">
        <span class="btn-text">Slide Effect</span>
        <span class="btn-slide-bg"></span>
      </button>
      
      <button class="btn btn-primary btn-bounce">
        <span class="btn-text">Bounce Effect</span>
      </button>
      
      <button class="btn btn-primary btn-rotate">
        <span class="btn-text">Rotate Effect</span>
      </button>
    </div>
  </div>

  
  <div class="button-section">
    <h3>Icon Buttons</h3>
    <div class="button-grid">
      <button class="btn btn-primary btn-icon">
        <svg class="btn-icon-svg" viewBox="0 0 24 24" fill="currentColor">
          <path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
        </svg>
        <span class="btn-text">Add Item</span>
      </button>
      
      <button class="btn btn-secondary btn-icon">
        <svg class="btn-icon-svg" viewBox="0 0 24 24" fill="currentColor">
          <path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/>
        </svg>
        <span class="btn-text">Edit</span>
      </button>
      
      <button class="btn btn-danger btn-icon">
        <svg class="btn-icon-svg" viewBox="0 0 24 24" fill="currentColor">
          <path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/>
        </svg>
        <span class="btn-text">Delete</span>
      </button>
      
      <button class="btn btn-outline btn-icon-only" aria-label="Settings">
        <svg class="btn-icon-svg" viewBox="0 0 24 24" fill="currentColor">
          <path d="M19.14,12.94c0.04-0.3,0.06-0.61,0.06-0.94c0-0.32-0.02-0.64-0.07-0.94l2.03-1.58c0.18-0.14,0.23-0.41,0.12-0.61 l-1.92-3.32c-0.12-0.22-0.37-0.29-0.59-0.22l-2.39,0.96c-0.5-0.38-1.03-0.7-1.62-0.94L14.4,2.81c-0.04-0.24-0.24-0.41-0.48-0.41 h-3.84c-0.24,0-0.43,0.17-0.47,0.41L9.25,5.35C8.66,5.59,8.12,5.92,7.63,6.29L5.24,5.33c-0.22-0.08-0.47,0-0.59,0.22L2.74,8.87 C2.62,9.08,2.66,9.34,2.86,9.48l2.03,1.58C4.84,11.36,4.8,11.69,4.8,12s0.02,0.64,0.07,0.94l-2.03,1.58 c-0.18,0.14-0.23,0.41-0.12,0.61l1.92,3.32c0.12,0.22,0.37,0.29,0.59,0.22l2.39-0.96c0.5,0.38,1.03,0.7,1.62,0.94l0.36,2.54 c0.05,0.24,0.24,0.41,0.48,0.41h3.84c0.24,0,0.44-0.17,0.47-0.41l0.36-2.54c0.59-0.24,1.13-0.56,1.62-0.94l2.39,0.96 c0.22,0.08,0.47,0,0.59-0.22l1.92-3.32c0.12-0.22,0.07-0.47-0.12-0.61L19.14,12.94z M12,15.6c-1.98,0-3.6-1.62-3.6-3.6 s1.62-3.6,3.6-3.6s3.6,1.62,3.6,3.6S13.98,15.6,12,15.6z"/>
        </svg>
      </button>
      
      <button class="btn btn-ghost btn-icon-only" aria-label="Search">
        <svg class="btn-icon-svg" viewBox="0 0 24 24" fill="currentColor">
          <path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>
        </svg>
      </button>
      
      <button class="btn btn-primary btn-icon-only" aria-label="Favorite">
        <svg class="btn-icon-svg" viewBox="0 0 24 24" fill="currentColor">
          <path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>
        </svg>
      </button>
    </div>
  </div>

  
  <div class="button-section">
    <h3>Loading States</h3>
    <div class="button-grid">
      <button class="btn btn-primary btn-loading">
        <span class="btn-spinner"></span>
        <span class="btn-text">Loading...</span>
      </button>
      
      <button class="btn btn-secondary btn-loading-dots">
        <span class="btn-text">Processing</span>
        <span class="btn-dots">
          <span class="dot"></span>
          <span class="dot"></span>
          <span class="dot"></span>
        </span>
      </button>
      
      <button class="btn btn-outline btn-loading-progress">
        <span class="btn-text">Uploading</span>
        <span class="btn-progress">
          <span class="btn-progress-bar"></span>
        </span>
      </button>
      
      <button class="btn btn-gradient btn-pulse">
        <span class="btn-text">Syncing</span>
      </button>
    </div>
  </div>

  
  <div class="button-section">
    <h3>Size Variations</h3>
    <div class="button-grid">
      <button class="btn btn-primary btn-small">
        <span class="btn-text">Small</span>
      </button>
      
      <button class="btn btn-primary btn-medium">
        <span class="btn-text">Medium</span>
      </button>
      
      <button class="btn btn-primary btn-large">
        <span class="btn-text">Large</span>
      </button>
      
      <button class="btn btn-primary btn-extra-large">
        <span class="btn-text">Extra Large</span>
      </button>
    </div>
  </div>

  
  <div class="button-section">
    <h3>Special Effects</h3>
    <div class="button-grid">
      <button class="btn btn-neon">
        <span class="btn-text">Neon Effect</span>
      </button>
      
      <button class="btn btn-glass">
        <span class="btn-text">Glass Effect</span>
      </button>
      
      <button class="btn btn-3d">
        <span class="btn-text">3D Effect</span>
      </button>
      
      <button class="btn btn-liquid">
        <span class="btn-text">Liquid Effect</span>
        <span class="btn-liquid-bg"></span>
      </button>
      
      <button class="btn btn-magnetic">
        <span class="btn-text">Magnetic Effect</span>
      </button>
      
      <button class="btn btn-particle">
        <span class="btn-text">Particle Effect</span>
        <canvas class="btn-particle-canvas"></canvas>
      </button>
    </div>
  </div>

  
  <div class="button-section">
    <h3>Toggle Buttons</h3>
    <div class="button-grid">
      <button class="btn btn-toggle" data-toggle="false">
        <span class="btn-text">Toggle Me</span>
      </button>
      
      <button class="btn btn-switch" data-switch="false">
        <span class="btn-switch-track">
          <span class="btn-switch-thumb"></span>
        </span>
        <span class="btn-text">Switch</span>
      </button>
      
      <button class="btn btn-checkbox" data-checked="false">
        <span class="btn-checkbox-mark">
          <svg viewBox="0 0 24 24" fill="currentColor">
            <path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/>
          </svg>
        </span>
        <span class="btn-text">Checkbox</span>
      </button>
    </div>
  </div>
</div>
.button-demo-container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 2rem;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
  min-height: 100vh;
}

.button-section {
  margin-bottom: 4rem;
  padding: 2rem;
  background: white;
  border-radius: 16px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
}

.button-section h3 {
  margin: 0 0 2rem 0;
  font-size: 1.5rem;
  font-weight: 700;
  color: #1a1a1a;
  text-align: center;
  position: relative;
}

.button-section h3::after {
  content: '';
  position: absolute;
  bottom: -0.5rem;
  left: 50%;
  transform: translateX(-50%);
  width: 60px;
  height: 3px;
  background: linear-gradient(90deg, #3b82f6, #8b5cf6);
  border-radius: 2px;
}

.button-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1.5rem;
  align-items: center;
  justify-items: center;
}.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.75rem 1.5rem;
  border: none;
  border-radius: 8px;
  font-size: 1rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: all 0.3s ease;
  overflow: hidden;
  user-select: none;
  outline: none;
  min-width: 120px;
  background: transparent;
}

.btn:focus {
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3);
}

.btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none !important;
}

.btn-text {
  position: relative;
  z-index: 2;
  transition: all 0.3s ease;
}

.btn-icon-svg {
  width: 20px;
  height: 20px;
  transition: all 0.3s ease;
}.btn-primary {
  background: linear-gradient(135deg, #3b82f6, #1d4ed8);
  color: white;
  box-shadow: 0 4px 15px rgba(59, 130, 246, 0.3);
}

.btn-primary:hover {
  background: linear-gradient(135deg, #2563eb, #1e40af);
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(59, 130, 246, 0.4);
}

.btn-secondary {
  background: linear-gradient(135deg, #6b7280, #4b5563);
  color: white;
  box-shadow: 0 4px 15px rgba(107, 114, 128, 0.3);
}

.btn-secondary:hover {
  background: linear-gradient(135deg, #4b5563, #374151);
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(107, 114, 128, 0.4);
}

.btn-outline {
  background: transparent;
  color: #3b82f6;
  border: 2px solid #3b82f6;
}

.btn-outline:hover {
  background: #3b82f6;
  color: white;
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(59, 130, 246, 0.3);
}

.btn-ghost {
  background: transparent;
  color: #6b7280;
  border: 1px solid transparent;
}

.btn-ghost:hover {
  background: #f3f4f6;
  color: #374151;
  border-color: #e5e7eb;
  transform: translateY(-1px);
}

.btn-gradient {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
}

.btn-gradient:hover {
  background: linear-gradient(135deg, #5a67d8 0%, #6b46c1 100%);
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
}

.btn-danger {
  background: linear-gradient(135deg, #ef4444, #dc2626);
  color: white;
  box-shadow: 0 4px 15px rgba(239, 68, 68, 0.3);
}

.btn-danger:hover {
  background: linear-gradient(135deg, #dc2626, #b91c1c);
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(239, 68, 68, 0.4);
}.btn-scale:hover {
  transform: scale(1.05);
}

.btn-glow {
  position: relative;
}

.btn-glow::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  border-radius: 8px;
  background: linear-gradient(135deg, #3b82f6, #1d4ed8);
  opacity: 0;
  transition: opacity 0.3s ease;
  z-index: -1;
  filter: blur(10px);
}

.btn-glow:hover::before {
  opacity: 0.7;
}

.btn-ripple {
  overflow: hidden;
}

.btn-ripple .btn-ripple {
  position: absolute;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.6);
  transform: scale(0);
  animation: ripple 0.6s linear;
  pointer-events: none;
}

@keyframes ripple {
  to {
    transform: scale(4);
    opacity: 0;
  }
}

.btn-slide {
  overflow: hidden;
}

.btn-slide-bg {
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: rgba(255, 255, 255, 0.1);
  transition: left 0.3s ease;
  z-index: 1;
}

.btn-slide:hover .btn-slide-bg {
  left: 0;
}

.btn-bounce:hover {
  animation: bounce 0.6s ease;
}

@keyframes bounce {
  0%, 20%, 60%, 100% {
    transform: translateY(0);
  }
  40% {
    transform: translateY(-10px);
  }
  80% {
    transform: translateY(-5px);
  }
}

.btn-rotate:hover {
  transform: rotateY(180deg);
}.btn-icon {
  gap: 0.75rem;
}

.btn-icon-only {
  width: 48px;
  height: 48px;
  padding: 0;
  border-radius: 50%;
  min-width: auto;
}

.btn-icon:hover .btn-icon-svg {
  transform: scale(1.1);
}.btn-loading {
  pointer-events: none;
}

.btn-spinner {
  width: 20px;
  height: 20px;
  border: 2px solid transparent;
  border-top: 2px solid currentColor;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.btn-loading-dots .btn-dots {
  display: flex;
  gap: 4px;
  margin-left: 8px;
}

.btn-dots .dot {
  width: 6px;
  height: 6px;
  background: currentColor;
  border-radius: 50%;
  animation: dotPulse 1.4s ease-in-out infinite both;
}

.btn-dots .dot:nth-child(1) { animation-delay: -0.32s; }
.btn-dots .dot:nth-child(2) { animation-delay: -0.16s; }

@keyframes dotPulse {
  0%, 80%, 100% {
    transform: scale(0.8);
    opacity: 0.5;
  }
  40% {
    transform: scale(1);
    opacity: 1;
  }
}

.btn-loading-progress {
  position: relative;
  overflow: hidden;
}

.btn-progress {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 3px;
  background: rgba(255, 255, 255, 0.2);
}

.btn-progress-bar {
  display: block;
  width: 0;
  height: 100%;
  background: currentColor;
  animation: progressBar 2s ease-in-out infinite;
}

@keyframes progressBar {
  0% { width: 0; }
  50% { width: 70%; }
  100% { width: 100%; }
}

.btn-pulse {
  animation: pulse 2s ease-in-out infinite;
}

@keyframes pulse {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.7;
  }
}.btn-small {
  padding: 0.5rem 1rem;
  font-size: 0.875rem;
  min-width: 80px;
}

.btn-medium {
  padding: 0.75rem 1.5rem;
  font-size: 1rem;
  min-width: 120px;
}

.btn-large {
  padding: 1rem 2rem;
  font-size: 1.125rem;
  min-width: 160px;
}

.btn-extra-large {
  padding: 1.25rem 2.5rem;
  font-size: 1.25rem;
  min-width: 200px;
}.btn-neon {
  background: transparent;
  color: #00ffff;
  border: 2px solid #00ffff;
  text-shadow: 0 0 10px #00ffff;
  box-shadow: 0 0 20px rgba(0, 255, 255, 0.3);
}

.btn-neon:hover {
  background: #00ffff;
  color: #000;
  text-shadow: none;
  box-shadow: 0 0 30px rgba(0, 255, 255, 0.6);
}

.btn-glass {
  background: rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.2);
  color: #333;
}

.btn-glass:hover {
  background: rgba(255, 255, 255, 0.2);
  transform: translateY(-2px);
}

.btn-3d {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  box-shadow: 0 8px 0 #5a67d8, 0 12px 20px rgba(0, 0, 0, 0.3);
  transform: translateY(0);
}

.btn-3d:hover {
  transform: translateY(4px);
  box-shadow: 0 4px 0 #5a67d8, 0 8px 15px rgba(0, 0, 0, 0.3);
}

.btn-3d:active {
  transform: translateY(8px);
  box-shadow: 0 0 0 #5a67d8, 0 4px 10px rgba(0, 0, 0, 0.3);
}

.btn-liquid {
  background: #3b82f6;
  color: white;
  overflow: hidden;
}

.btn-liquid-bg {
  position: absolute;
  top: 100%;
  left: 0;
  width: 100%;
  height: 100%;
  background: #1d4ed8;
  transition: top 0.3s ease;
  z-index: 1;
}

.btn-liquid:hover .btn-liquid-bg {
  top: 0;
}

.btn-magnetic {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  transition: all 0.1s ease;
}

.btn-particle {
  background: #1a1a1a;
  color: white;
  position: relative;
  overflow: hidden;
}

.btn-particle-canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 1;
}.btn-toggle {
  background: #e5e7eb;
  color: #6b7280;
  transition: all 0.3s ease;
}

.btn-toggle.active {
  background: #3b82f6;
  color: white;
}

.btn-switch {
  background: transparent;
  color: #6b7280;
  padding: 0.5rem;
  gap: 1rem;
}

.btn-switch-track {
  width: 48px;
  height: 24px;
  background: #e5e7eb;
  border-radius: 12px;
  position: relative;
  transition: background 0.3s ease;
}

.btn-switch-thumb {
  width: 20px;
  height: 20px;
  background: white;
  border-radius: 50%;
  position: absolute;
  top: 2px;
  left: 2px;
  transition: transform 0.3s ease;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

.btn-switch.active .btn-switch-track {
  background: #3b82f6;
}

.btn-switch.active .btn-switch-thumb {
  transform: translateX(24px);
}

.btn-checkbox {
  background: transparent;
  color: #6b7280;
  border: 2px solid #d1d5db;
  gap: 1rem;
}

.btn-checkbox-mark {
  width: 20px;
  height: 20px;
  border: 2px solid #d1d5db;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.3s ease;
}

.btn-checkbox-mark svg {
  width: 14px;
  height: 14px;
  opacity: 0;
  transform: scale(0);
  transition: all 0.3s ease;
}

.btn-checkbox.active {
  border-color: #3b82f6;
  color: #3b82f6;
}

.btn-checkbox.active .btn-checkbox-mark {
  background: #3b82f6;
  border-color: #3b82f6;
}

.btn-checkbox.active .btn-checkbox-mark svg {
  opacity: 1;
  transform: scale(1);
  color: white;
}.dark .button-section {
  background: #1f2937;
  border-color: #374151;
}

.dark .button-section h3 {
  color: #f9fafb;
}

.dark .btn-ghost {
  color: #d1d5db;
}

.dark .btn-ghost:hover {
  background: #374151;
  color: #f3f4f6;
  border-color: #4b5563;
}

.dark .btn-glass {
  background: rgba(0, 0, 0, 0.2);
  color: #e5e7eb;
  border-color: rgba(255, 255, 255, 0.1);
}

.dark .btn-toggle {
  background: #374151;
  color: #d1d5db;
}

.dark .btn-switch-track {
  background: #374151;
}

.dark .btn-checkbox {
  border-color: #4b5563;
  color: #d1d5db;
}

.dark .btn-checkbox-mark {
  border-color: #4b5563;
}@media (max-width: 768px) {
  .button-demo-container {
    padding: 1rem;
  }
  
  .button-section {
    padding: 1.5rem;
    margin-bottom: 2rem;
  }
  
  .button-grid {
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 1rem;
  }
  
  .btn {
    min-width: 100px;
    padding: 0.625rem 1.25rem;
    font-size: 0.875rem;
  }
  
  .btn-large,
  .btn-extra-large {
    padding: 0.75rem 1.5rem;
    font-size: 1rem;
    min-width: 120px;
  }
}

@media (max-width: 480px) {
  .button-grid {
    grid-template-columns: 1fr;
  }
  
  .btn {
    width: 100%;
    max-width: 280px;
  }
}@media (prefers-reduced-motion: reduce) {
  .btn,
  .btn-spinner,
  .btn-dots .dot,
  .btn-progress-bar,
  .btn-switch-thumb,
  .btn-checkbox-mark svg {
    transition: none;
    animation: none;
  }
}.btn:focus-visible {
  outline: 2px solid #3b82f6;
  outline-offset: 2px;
}@media (prefers-contrast: high) {
  .btn {
    border: 2px solid;
  }
  
  .btn-primary {
    background: #0000ff;
    border-color: #0000ff;
  }
  
  .btn-secondary {
    background: #666666;
    border-color: #666666;
  }
  
  .btn-danger {
    background: #ff0000;
    border-color: #ff0000;
  }
}
class AnimatedButtonComponents {
  constructor() {
    this.buttons = new Map();
    this.rippleButtons = [];
    this.particleButtons = [];
    this.magneticButtons = [];
    
    this.init();
  }

  init() {
    this.setupEventListeners();
    this.initializeRippleEffect();
    this.initializeParticleEffect();
    this.initializeMagneticEffect();
    this.initializeToggleButtons();
    this.setupAccessibility();
  }

  setupEventListeners() {
    document.addEventListener('click', (e) => {
      const button = e.target.closest('.btn');
      if (!button) return;

      if (button.classList.contains('btn-toggle')) {
        this.handleToggle(button);
      }
      
      if (button.classList.contains('btn-switch')) {
        this.handleSwitch(button);
      }
      
      if (button.classList.contains('btn-checkbox')) {
        this.handleCheckbox(button);
      }

      if (button.classList.contains('btn-ripple')) {
        this.createRipple(e, button);
      }

      this.dispatchButtonEvent('buttonClick', {
        button,
        type: this.getButtonType(button)
      });
    });

    document.addEventListener('keydown', (e) => {
      if (e.key === 'Enter' || e.key === ' ') {
        const button = e.target.closest('.btn');
        if (button) {
          e.preventDefault();
          button.click();
        }
      }
    });
  }

  initializeRippleEffect() {
    const rippleButtons = document.querySelectorAll('.btn-ripple');
    rippleButtons.forEach(button => {
      this.rippleButtons.push(button);
    });
  }

  createRipple(event, button) {
    const ripple = document.createElement('span');
    const rect = button.getBoundingClientRect();
    const size = Math.max(rect.width, rect.height);
    const x = event.clientX - rect.left - size / 2;
    const y = event.clientY - rect.top - size / 2;
    
    ripple.className = 'btn-ripple';
    ripple.style.width = ripple.style.height = size + 'px';
    ripple.style.left = x + 'px';
    ripple.style.top = y + 'px';

    const existingRipples = button.querySelectorAll('.btn-ripple');
    existingRipples.forEach(r => r.remove());
    
    button.appendChild(ripple);
    
    setTimeout(() => {
      ripple.remove();
    }, 600);
  }

  initializeParticleEffect() {
    const particleButtons = document.querySelectorAll('.btn-particle');
    particleButtons.forEach(button => {
      const canvas = button.querySelector('.btn-particle-canvas');
      if (canvas) {
        this.setupParticleCanvas(button, canvas);
        this.particleButtons.push({ button, canvas });
      }
    });
  }

  setupParticleCanvas(button, canvas) {
    const ctx = canvas.getContext('2d');
    const particles = [];
    
    const resizeCanvas = () => {
      const rect = button.getBoundingClientRect();
      canvas.width = rect.width;
      canvas.height = rect.height;
    };
    
    resizeCanvas();
    window.addEventListener('resize', resizeCanvas);
    
    button.addEventListener('mouseenter', () => {
      this.startParticleAnimation(ctx, canvas, particles);
    });
    
    button.addEventListener('mouseleave', () => {
      particles.length = 0;
    });
  }

  startParticleAnimation(ctx, canvas, particles) {
    const createParticle = () => {
      return {
        x: Math.random() * canvas.width,
        y: Math.random() * canvas.height,
        vx: (Math.random() - 0.5) * 2,
        vy: (Math.random() - 0.5) * 2,
        life: 1,
        decay: Math.random() * 0.02 + 0.01
      };
    };
    
    const animate = () => {
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      if (particles.length < 20 && Math.random() < 0.3) {
        particles.push(createParticle());
      }

      for (let i = particles.length - 1; i >= 0; i--) {
        const particle = particles[i];
        
        particle.x += particle.vx;
        particle.y += particle.vy;
        particle.life -= particle.decay;
        
        if (particle.life <= 0) {
          particles.splice(i, 1);
          continue;
        }
        
        ctx.save();
        ctx.globalAlpha = particle.life;
        ctx.fillStyle = '#ffffff';
        ctx.beginPath();
        ctx.arc(particle.x, particle.y, 2, 0, Math.PI * 2);
        ctx.fill();
        ctx.restore();
      }
      
      if (particles.length > 0) {
        requestAnimationFrame(animate);
      }
    };
    
    animate();
  }

  initializeMagneticEffect() {
    const magneticButtons = document.querySelectorAll('.btn-magnetic');
    magneticButtons.forEach(button => {
      this.setupMagneticEffect(button);
      this.magneticButtons.push(button);
    });
  }

  setupMagneticEffect(button) {
    button.addEventListener('mousemove', (e) => {
      const rect = button.getBoundingClientRect();
      const x = e.clientX - rect.left - rect.width / 2;
      const y = e.clientY - rect.top - rect.height / 2;
      
      const distance = Math.sqrt(x * x + y * y);
      const maxDistance = Math.max(rect.width, rect.height) / 2;
      
      if (distance < maxDistance) {
        const strength = (maxDistance - distance) / maxDistance;
        const moveX = x * strength * 0.3;
        const moveY = y * strength * 0.3;
        
        button.style.transform = `translate(${moveX}px, ${moveY}px)`;
      }
    });
    
    button.addEventListener('mouseleave', () => {
      button.style.transform = 'translate(0, 0)';
    });
  }

  initializeToggleButtons() {
    const toggleButtons = document.querySelectorAll('.btn-toggle, .btn-switch, .btn-checkbox');
    toggleButtons.forEach(button => {
      const initialState = button.dataset.toggle === 'true' || 
                          button.dataset.switch === 'true' || 
                          button.dataset.checked === 'true';
      
      if (initialState) {
        button.classList.add('active');
      }
      
      this.buttons.set(button, {
        type: this.getButtonType(button),
        state: initialState
      });
    });
  }

  handleToggle(button) {
    const buttonData = this.buttons.get(button);
    const newState = !buttonData.state;
    
    buttonData.state = newState;
    button.dataset.toggle = newState.toString();
    
    if (newState) {
      button.classList.add('active');
    } else {
      button.classList.remove('active');
    }
    
    this.dispatchButtonEvent('buttonToggle', {
      button,
      state: newState
    });
  }

  handleSwitch(button) {
    const buttonData = this.buttons.get(button);
    const newState = !buttonData.state;
    
    buttonData.state = newState;
    button.dataset.switch = newState.toString();
    
    if (newState) {
      button.classList.add('active');
    } else {
      button.classList.remove('active');
    }
    
    this.dispatchButtonEvent('buttonSwitch', {
      button,
      state: newState
    });
  }

  handleCheckbox(button) {
    const buttonData = this.buttons.get(button);
    const newState = !buttonData.state;
    
    buttonData.state = newState;
    button.dataset.checked = newState.toString();
    
    if (newState) {
      button.classList.add('active');
    } else {
      button.classList.remove('active');
    }
    
    this.dispatchButtonEvent('buttonCheck', {
      button,
      checked: newState
    });
  }

  getButtonType(button) {
    if (button.classList.contains('btn-toggle')) return 'toggle';
    if (button.classList.contains('btn-switch')) return 'switch';
    if (button.classList.contains('btn-checkbox')) return 'checkbox';
    if (button.classList.contains('btn-primary')) return 'primary';
    if (button.classList.contains('btn-secondary')) return 'secondary';
    if (button.classList.contains('btn-outline')) return 'outline';
    if (button.classList.contains('btn-ghost')) return 'ghost';
    if (button.classList.contains('btn-gradient')) return 'gradient';
    if (button.classList.contains('btn-danger')) return 'danger';
    return 'default';
  }

  setupAccessibility() {

    const buttons = document.querySelectorAll('.btn');
    buttons.forEach(button => {
      if (!button.getAttribute('role')) {
        button.setAttribute('role', 'button');
      }
      
      if (!button.hasAttribute('tabindex')) {
        button.setAttribute('tabindex', '0');
      }

      if (button.classList.contains('btn-toggle') || 
          button.classList.contains('btn-switch') || 
          button.classList.contains('btn-checkbox')) {
        const isPressed = button.classList.contains('active');
        button.setAttribute('aria-pressed', isPressed.toString());
      }
    });
  }

  dispatchButtonEvent(eventName, detail) {
    const event = new CustomEvent(eventName, {
      detail,
      bubbles: true,
      cancelable: true
    });
    document.dispatchEvent(event);
  }

  setButtonState(button, state) {
    if (typeof button === 'string') {
      button = document.querySelector(button);
    }
    
    if (!button) return;
    
    const buttonData = this.buttons.get(button);
    if (!buttonData) return;
    
    buttonData.state = state;
    
    if (button.classList.contains('btn-toggle')) {
      button.dataset.toggle = state.toString();
    } else if (button.classList.contains('btn-switch')) {
      button.dataset.switch = state.toString();
    } else if (button.classList.contains('btn-checkbox')) {
      button.dataset.checked = state.toString();
    }
    
    if (state) {
      button.classList.add('active');
    } else {
      button.classList.remove('active');
    }
    
    button.setAttribute('aria-pressed', state.toString());
  }

  getButtonState(button) {
    if (typeof button === 'string') {
      button = document.querySelector(button);
    }
    
    const buttonData = this.buttons.get(button);
    return buttonData ? buttonData.state : null;
  }

  setLoadingState(button, loading = true) {
    if (typeof button === 'string') {
      button = document.querySelector(button);
    }
    
    if (!button) return;
    
    if (loading) {
      button.classList.add('btn-loading');
      button.disabled = true;
      button.setAttribute('aria-busy', 'true');
    } else {
      button.classList.remove('btn-loading');
      button.disabled = false;
      button.setAttribute('aria-busy', 'false');
    }
  }

  destroy() {

    this.rippleButtons = [];
    this.particleButtons = [];
    this.magneticButtons = [];
    this.buttons.clear();
  }
}

let animatedButtonComponents;
document.addEventListener('DOMContentLoaded', () => {
  animatedButtonComponents = new AnimatedButtonComponents();
});

if (typeof module !== 'undefined' && module.exports) {
  module.exports = AnimatedButtonComponents;
}

window.AnimatedButtonComponents = AnimatedButtonComponents;

Usage Examples

Basic Button Implementation


<button class="btn btn-primary btn-scale">
  <span class="btn-text">Click Me</span>
</button>


<button class="btn btn-secondary btn-icon">
  <svg class="btn-icon-svg" viewBox="0 0 24 24" fill="currentColor">
    <path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
  </svg>
  <span class="btn-text">Add Item</span>
</button>


<button class="btn btn-primary btn-loading">
  <span class="btn-spinner"></span>
  <span class="btn-text">Loading...</span>
</button>

JavaScript Integration


const buttonComponent = new AnimatedButtonComponents();

buttonComponent.setLoadingState('#submit-btn', true);

document.addEventListener('buttonClick', (e) => {
  console.log('Button clicked:', e.detail.button);
  console.log('Button type:', e.detail.type);
});

document.addEventListener('buttonToggle', (e) => {
  console.log('Toggle state:', e.detail.state);
});

buttonComponent.setButtonState('#my-toggle', true);

const isToggled = buttonComponent.getButtonState('#my-toggle');
console.log('Button is toggled:', isToggled);

Custom Button Creation


function createCustomButton(text, type = 'primary', effects = []) {
  const button = document.createElement('button');
  button.className = `btn btn-${type} ${effects.map(e => `btn-${e}`).join(' ')}`;
  
  const textSpan = document.createElement('span');
  textSpan.className = 'btn-text';
  textSpan.textContent = text;
  button.appendChild(textSpan);

  if (effects.includes('ripple')) {
    const rippleSpan = document.createElement('span');
    rippleSpan.className = 'btn-ripple';
    button.appendChild(rippleSpan);
  }
  
  return button;
}

const customButton = createCustomButton('Custom Button', 'gradient', ['scale', 'glow']);
document.body.appendChild(customButton);

API Reference

Methods

setButtonState(button, state)

Sets the state of a toggle, switch, or checkbox button.

Parameters:

  • button (Element|string): Button element or CSS selector
  • state (boolean): New state value
buttonComponent.setButtonState('#my-toggle', true);

getButtonState(button)

Gets the current state of a toggle, switch, or checkbox button.

Parameters:

  • button (Element|string): Button element or CSS selector

Returns: boolean|null

const state = buttonComponent.getButtonState('#my-toggle');

setLoadingState(button, loading)

Sets the loading state of a button.

Parameters:

  • button (Element|string): Button element or CSS selector
  • loading (boolean): Loading state (default: true)
buttonComponent.setLoadingState('#submit-btn', true);

destroy()

Cleans up all event listeners and animations.

buttonComponent.destroy();

Events

buttonClick

Fired when any button is clicked.

Event Detail:

  • button (Element): The clicked button element
  • type (string): Button type (primary, secondary, etc.)
document.addEventListener('buttonClick', (e) => {
  console.log('Clicked button:', e.detail.button);
});

buttonToggle

Fired when a toggle button state changes.

Event Detail:

  • button (Element): The toggle button element
  • state (boolean): New toggle state
document.addEventListener('buttonToggle', (e) => {
  console.log('Toggle state:', e.detail.state);
});

buttonSwitch

Fired when a switch button state changes.

Event Detail:

  • button (Element): The switch button element
  • state (boolean): New switch state
document.addEventListener('buttonSwitch', (e) => {
  console.log('Switch state:', e.detail.state);
});

buttonCheck

Fired when a checkbox button state changes.

Event Detail:

  • button (Element): The checkbox button element
  • checked (boolean): New checked state
document.addEventListener('buttonCheck', (e) => {
  console.log('Checkbox checked:', e.detail.checked);
});

CSS Classes

Button Types

  • .btn-primary - Primary button style
  • .btn-secondary - Secondary button style
  • .btn-outline - Outline button style
  • .btn-ghost - Ghost button style
  • .btn-gradient - Gradient button style
  • .btn-danger - Danger button style

Animation Effects

  • .btn-scale - Scale animation on hover
  • .btn-glow - Glow effect on hover
  • .btn-ripple - Ripple effect on click
  • .btn-slide - Slide background effect
  • .btn-bounce - Bounce animation on hover
  • .btn-rotate - Rotation effect on hover

Special Effects

  • .btn-neon - Neon glow effect
  • .btn-glass - Glass morphism effect
  • .btn-3d - 3D button effect
  • .btn-liquid - Liquid fill effect
  • .btn-magnetic - Magnetic mouse tracking
  • .btn-particle - Particle animation effect

Sizes

  • .btn-small - Small button size
  • .btn-medium - Medium button size (default)
  • .btn-large - Large button size
  • .btn-extra-large - Extra large button size

States

  • .btn-loading - Loading state
  • .btn-loading-dots - Loading with dots animation
  • .btn-loading-progress - Loading with progress bar
  • .btn-pulse - Pulsing animation

Customization

CSS Variables

Customize the button appearance using CSS variables:

:root {
  --btn-primary-bg: linear-gradient(135deg, #3b82f6, #1d4ed8);
  --btn-primary-hover-bg: linear-gradient(135deg, #2563eb, #1e40af);
  --btn-primary-shadow: 0 4px 15px rgba(59, 130, 246, 0.3);
  --btn-primary-hover-shadow: 0 8px 25px rgba(59, 130, 246, 0.4);
  
  --btn-border-radius: 8px;
  --btn-padding: 0.75rem 1.5rem;
  --btn-font-size: 1rem;
  --btn-font-weight: 600;
  
  --btn-transition: all 0.3s ease;
  --btn-hover-transform: translateY(-2px);
  
  --btn-focus-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3);
}

Custom Animations

Add your own button animations:

.btn-custom-effect {
  position: relative;
  overflow: hidden;
}

.btn-custom-effect::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
  transition: left 0.5s ease;
}

.btn-custom-effect:hover::before {
  left: 100%;
}

Theme Integration

.theme-light {
  --btn-text-color: #1f2937;
  --btn-bg-color: #ffffff;
  --btn-border-color: #e5e7eb;
}.theme-dark {
  --btn-text-color: #f9fafb;
  --btn-bg-color: #1f2937;
  --btn-border-color: #374151;
}

Accessibility

ARIA Support

The component automatically adds appropriate ARIA attributes:

  • role="button" for all buttons
  • aria-pressed for toggle buttons
  • aria-busy for loading states
  • tabindex="0" for keyboard navigation

Keyboard Navigation

  • Enter/Space: Activate button
  • Tab: Navigate between buttons
  • Escape: Cancel loading state (if implemented)

Screen Reader Support


<button class="btn btn-primary" aria-label="Submit form">
  <span class="btn-text">Submit</span>
</button>


<button class="btn btn-danger" aria-describedby="delete-warning">
  <span class="btn-text">Delete</span>
</button>
<div id="delete-warning" class="sr-only">
  This action cannot be undone
</div>

Reduced Motion

The component respects prefers-reduced-motion settings:

@media (prefers-reduced-motion: reduce) {
  .btn {
    transition: none;
    animation: none;
  }
}

Browser Support

  • Chrome: 60+
  • Firefox: 55+
  • Safari: 12+
  • Edge: 79+
  • iOS Safari: 12+
  • Android Chrome: 60+

Fallbacks

For older browsers, the component gracefully degrades:

.button-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}.btn-glass {
  background: rgba(255, 255, 255, 0.9);
}

@supports (backdrop-filter: blur(10px)) {
  .btn-glass {
    background: rgba(255, 255, 255, 0.1);
    backdrop-filter: blur(10px);
  }
}

Performance Considerations

Optimization Tips

  1. Use CSS transforms instead of changing layout properties
  2. Limit particle effects to avoid performance issues
  3. Debounce rapid interactions for better UX
  4. Use will-change for frequently animated elements
.btn-animated {
  will-change: transform;
}

.btn-animated:hover {
  transform: translateY(-2px) scale(1.02);
}

Memory Management


window.addEventListener('beforeunload', () => {
  if (animatedButtonComponents) {
    animatedButtonComponents.destroy();
  }
});

Integration Examples

React Integration

x
import React, { useEffect, useRef } from 'react';

const AnimatedButton = ({ children, type = 'primary', effects = [], onClick }) => {
  const buttonRef = useRef(null);
  
  useEffect(() => {

    if (window.AnimatedButtonComponents && buttonRef.current) {

    }
  }, []);
  
  const handleClick = (e) => {
    if (onClick) {
      onClick(e);
    }
  };
  
  const className = `btn btn-${type} ${effects.map(e => `btn-${e}`).join(' ')}`;
  
  return (
    <button ref={buttonRef} className={className} onClick={handleClick}>
      <span className="btn-text">{children}</span>
    </button>
  );
};

<AnimatedButton type="primary" effects={['scale', 'glow']} onClick={handleSubmit}>
  Submit Form
</AnimatedButton>

Vue Integration

<template>
  <button 
    ref="buttonRef"
    :class="buttonClasses" 
    @click="handleClick"
  >
    <span class="btn-text">{{ children }}</span>
  </button>
</template>

<script>
export default {
  name: 'AnimatedButton',
  props: {
    type: {
      type: String,
      default: 'primary'
    },
    effects: {
      type: Array,
      default: () => []
    },
    children: {
      type: String,
      required: true
    }
  },
  computed: {
    buttonClasses() {
      return [
        'btn',
        `btn-${this.type}`,
        ...this.effects.map(effect => `btn-${effect}`)
      ].join(' ');
    }
  },
  mounted() {

  },
  methods: {
    handleClick(e) {
      this.$emit('click', e);
    }
  }
};
</script>

Angular Integration

import { Component, Input, Output, EventEmitter, ElementRef, AfterViewInit } from '@angular/core';

@Component({
  selector: 'app-animated-button',
  template: `
    <button [class]="buttonClasses" (click)="handleClick($event)">
      <span class="btn-text"><ng-content></ng-content></span>
    </button>
  `
})
export class AnimatedButtonComponent implements AfterViewInit {
  @Input() type: string = 'primary';
  @Input() effects: string[] = [];
  @Output() buttonClick = new EventEmitter<Event>();
  
  constructor(private elementRef: ElementRef) {}
  
  ngAfterViewInit() {

  }
  
  get buttonClasses(): string {
    return [
      'btn',
      `btn-${this.type}`,
      ...this.effects.map(effect => `btn-${effect}`)
    ].join(' ');
  }
  
  handleClick(event: Event) {
    this.buttonClick.emit(event);
  }
}

This comprehensive animated button component collection provides a wide variety of modern, accessible, and performant button styles with smooth animations and interactive effects. The component is designed to be easily customizable and integrates seamlessly with popular frameworks while maintaining excellent browser support and accessibility standards.

HTML

17

lines

CSS

61

lines


                <div class="button-demo-container">
  <button class="btn btn-primary">
    <span class="btn-text">Primary Button</span>
  </button>
  
  <button class="btn btn-secondary">
    <span class="btn-text">Secondary Button</span>
  </button>
  
  <button class="btn btn-outline">
    <span class="btn-text">Outline Button</span>
  </button>
  
  <button class="btn btn-gradient">
    <span class="btn-text">Gradient Button</span>
  </button>
</div>

              
17lines
442characters
HTMLLanguage

Related Code Snippets

Explore template packs

Need larger building blocks? Browse responsive landing pages and component bundles.

Open HTML Template Library ->