Submit Button with Pure CSS Loading Spinner

Many forms and apps will include a submit button (or similar) that, when clicked, will become temporarily disabled while some action is taking place. During the wait time, a good UI practice is to insert an animated loading indicator. This can be done with pure CSS while the JavaScript is just used to enable/disable the button while also performing some asynchronous action in the process. This could also be used when a general form submission is done synchronously.

Here is the HTML for the button:

<button>SUBMIT FORM<span class="spinner"></span></button>

Here is the CSS (commented):

/* This is the submit button styles */ button { display: block; margin: 0 auto; padding: .6em .8em; /* Font-size is the root value that determines size of spinner parts. Change this to whatever you want and spinner elements will size to match. */ font-size: 20px; font-weight: bold; border-radius: .4em; border: none; overflow: hidden; cursor: pointer; position: relative; transition: all 1s; } /* focus/disabled styles, you can change this for accessibility */ button:focus, button:disabled { outline: none; background: #aaa; } /* This is the space for the spinner to appear, applied to the button */ .spin { padding-left: 2.5em; display: block; } /* position of the spinner when it appears, you might have to change these values */ .spin .spinner { left: -.6em; top: .4em; width: 2.5em; display: block; position: absolute; } /* spinner animation */ @keyframes spinner { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* The actual spinner element is a pseudo-element */ .spin .spinner::before { content: ""; width: 1.5em; /* Size of the spinner */ height: 1.5em; /* Change as desired */ position: absolute; top: 50%; left: 50%; border-radius: 50%; border: solid .35em #999; /* Thickness/color of spinner track */ border-bottom-color: #555; /* Color of variant spinner piece */ animation: .8s linear infinite spinner; /* speed of spinner */ transform: translate(-50%, -50%); will-change: transform; } /* optional, but it will affect the size if changed */ *, *::before, *::after { box-sizing: border-box; }

Finally, the JavaScript:

let btn = document.querySelector('button'); btn.addEventListener('click', function () { // form submission starts // button is disabled btn.classList.add('spin'); btn.disabled = true; // This disables the whole form via the fieldset btn.form.firstElementChild.disabled = true; // this setTimeout call mimics some asyncronous action // you would have something else here window.setTimeout(function () { // when asyncronous action is done, remove the spinner // re-enable button/fieldset btn.classList.remove('spin'); btn.disabled = false; btn.form.firstElementChild.disabled = false; }, 4000); }, false);

And here is a live demo:

Some things worth noting:

  • The JavaScript uses a setTimeout() call to mimic what might happen using Ajax. This would be removed and replaced with whatever you code is doing during the button submission process.
  • The size of the spinner is based on the font-size set on the <button> element using pixels. Adjust this and the spinner size and position will change automatically to match via em units.
  • The button also disables the parent fieldset. This is optional, but it’s an added feature. You can disable this by removing the appropriate commented line in the code.
  • The HTML in the demo disables the form from being submitted. This is only for demo purposes.

Related: Ladda spinners by Hakim El Hattab

Note: To the best of our knowledge, the information above and the snippet are accurate and up to date. However, in case you notice something wrong, please report snippet or leave a comment below.
Back to Snippets

Or start the conversation in our Facebook group for WordPress professionals. Find answers, share tips, and get help from other WordPress experts. Join now (it’s free)!

Most Searched Articles

14 of the Best JavaScript Libraries and Frameworks to Try Out in 2020

In this post, we look at the best JavaScript libraries and frameworks to try out this year. Why? Well, with JavaScript being available in every web browser, this makes it the most accessible programming language of ...

50+ Best Free WordPress Themes for 2020 (Responsive, Mobile-Ready, Beautiful)

If you're looking for only the best free WordPress themes in the market for this year, then you're in the right place. We have more than 60+ such themes for you right ...

10+ Best WordPress Hosting Providers of 2020 Compared & Tested

Looking for the best WordPress hosting that you can actually afford? We did the testing for you. Here are 10 best hosts on the market ...

Handpicked Articles

How to Make a WordPress Website: Ultimate Guide for Beginners and Advanced Users Alike

Many people wonder how to make a WordPress website. They’ve heard about WordPress, its incredible popularity, excellent features and designs, and now they want to join the pack and build a WordPress website of their own. So, where does one get ...

How to Start an eCommerce Business From Scratch (In 10 Steps)

Is 2020 going to be the year you learn how to start an eCommerce business from scratch? You’re certainly in the right place! This guide will give you a roadmap to getting from 0 to a fully functional eCommerce business. ...

Scroll to Top