Back to Components
Animated Success Button — Smooth Loading & Checkmark Transition
Component

Animated Success Button — Smooth Loading & Checkmark Transition

CodewithLord
October 9, 2025

A modern animated button built using HTML, CSS, and JavaScript that visually transitions through three states — idle, loading, and success.

🧠 Description

A modern animated button built using HTML, CSS, and JavaScript that visually transitions through three states — idle, loading, and success. When clicked, the button replaces its text with a spinning loader animation, simulating a background process (like a form submission). After a short delay, the loader switches to a success checkmark before returning to its original state.


💻 HTML Code


1<!DOCTYPE html> 2<html lang="en"> 3<head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <title>CodewithLord - Animated Button</title> 7 <link rel="stylesheet" href="style.css"> 8</head> 9<body> 10 11<button class="animated-button" id="animatedButton"> 12 <div class="button-content"> 13 <svg class="loader" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 14 <path stroke="none" d="M0 0h24v24H0z" fill="none"/> 15 <path d="M12 3a9 9 0 1 0 9 9"/> 16 </svg> 17 18 <svg class="check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 19 <path stroke="none" d="M0 0h24v24H0z" fill="none"/> 20 <path d="M9 12l2 2l4 -4"/> 21 </svg> 22 23 <span class="button-text">Click Me</span> 24 </div> 25</button> 26 27<script src="script.js"></script> 28</body> 29</html> 30

HTML Structure Explanation

The HTML defines a single button element with the class animated-button. Inside it, there’s a wrapper "div" called button-content, which holds three main elements:

Loader SVG: A circular stroke animation that rotates to represent “loading”.

Checkmark SVG: A success indicator shown after loading completes.

Text span: Displays the default button label ("Click Me").

The SVG icons are scalable vector graphics — they allow for crisp animations without external image files.

The JavaScript manipulates these inner elements dynamically to switch between states.


CSS Code


1body { 2 display: flex; 3 justify-content: center; 4 align-items: center; 5 height: 100vh; 6 background: #121212; 7} 8 9.animated-button { 10 background-color: #22c55e; 11 color: white; 12 padding: 12px 24px; 13 border: none; 14 border-radius: 9999px; 15 cursor: pointer; 16 font-weight: bold; 17 display: inline-flex; 18 align-items: center; 19 gap: 8px; 20 overflow: hidden; 21 position: relative; 22 font-family: sans-serif; 23} 24 25.button-content { 26 display: flex; 27 align-items: center; 28 gap: 8px; 29 position: relative; 30} 31 32.loader, .check { 33 width: 0; 34 height: 24px; 35 display: none; 36 transform: scale(0.5); 37} 38 39/* Rotate animation for loader */ 40@keyframes rotate { 41 0% { transform: rotate(0deg) scale(0.5); } 42 100% { transform: rotate(360deg) scale(0.5); } 43} 44 45

Body Setup

The body uses Flexbox to center the button both vertically and horizontally.

The background is dark (#121212), giving the button contrast and focus.

Button Styling

The button has:

A green background (#22c55e — Tailwind’s “emerald” tone).

White text for contrast.

A pill shape achieved via a large border-radius (9999px).

Padding, bold font, and spacing between inner elements.

It uses inline-flex to align the icons and text horizontally.

Inner Elements

The .button-content is a flex container that holds the loader, checkmark, and text neatly aligned.

The .loader and .check are hidden by default (display: none and width: 0).

Both start at a scaled-down size (0.5) for a subtle effect.

Animations

The @keyframes rotate animation rotates the loader 360° infinitely while keeping it scaled down.

This rotation gives the visual cue that a process is happening.

Visual Flow

Initially: Only text ("Click Me") is visible.

During loading: The loader appears, spinning beside the faded text.

On success: The loader disappears, replaced by the checkmark icon.

After a short delay: The checkmark fades out, and the button resets to its initial look.


Javascipt Code


1const button = document.getElementById("animatedButton"); 2const loader = button.querySelector(".loader"); 3const check = button.querySelector(".check"); 4const text = button.querySelector(".button-text"); 5 6async function animateLoading() { 7 loader.style.display = "block"; 8 loader.style.width = "24px"; 9 loader.style.animation = "rotate 0.6s linear infinite"; 10 text.style.opacity = "0.5"; 11} 12 13async function animateSuccess() { 14 loader.style.display = "none"; 15 loader.style.animation = ""; 16 17 check.style.display = "block"; 18 check.style.width = "36px"; // increased from 24px 19 check.style.height = "36px"; // added height 20 21 setTimeout(() => { 22 check.style.display = "none"; 23 text.style.opacity = "1"; 24 }, 2000); 25} 26 27button.addEventListener("click", async () => { 28 await animateLoading(); 29 30 // Simulate async action (e.g., form submission) 31 setTimeout(async () => { 32 await animateSuccess(); 33 }, 1000); 34}); 35

The JavaScript controls the state transitions of the button.

Element Selection

The script first grabs references to the button, loader, checkmark, and text.

animateLoading() Function

Triggered immediately after a click.

It:

Displays the loader (display: block).

Sets its width to 24px and starts the infinite rotation animation.

Fades the text slightly (opacity: 0.5) to show that the action is in progress.

animateSuccess() Function

Called after a short delay to represent a completed action.

It:

Hides the loader and removes its rotation animation.

Displays the checkmark, enlarging it for emphasis (36px size).

After 2 seconds, hides the checkmark and restores the text opacity to full (1), resetting the button.

Click Event Listener

When the button is clicked:

It runs animateLoading().

Waits for 1 second (simulating a process such as an API call).

Then runs animateSuccess() to show the checkmark feedback.

Smooth User Experience

The timing (1000ms load, 2000ms success display) ensures users clearly see each phase.

These async animations mimic real-world processes like saving data or submitting forms.

Love this component?

Explore more components and build amazing UIs.

View All Components