DEV Community

Cover image for Create a Button with 
a Loading Spinner in HTML & CSS 🔥

Create a Button with a Loading Spinner in HTML & CSS 🔥

Dom (dcode)
Web Developer from Australia that runs the YouTube Channel 'dcode'!
・3 min read

In today's post I'll be showing you how to use HTML and CSS to create an awesome looking button that features a loading spinner when clicked on.

Source Code & Preview

If you want to follow a long with the complete source code, you can find it here.

Video Tutorial

If you prefer this tutorial in the form of a video, you can watch it on my YouTube channel, dcode.

Also, consider subscribing to my channel if you're interested in web development 😁


Let's begin by writing the HTML for the button. This is going to be fairly straightforward. We create a <button> with a class of button and use a <span> for the text inside of it.

<button type="button" class="button">
    <span class="button__text">Save Changes</span>
Enter fullscreen mode Exit fullscreen mode

That's all we need for the HTML. Let's move onto the CSS 🙂


Here's where the majority of the code is placed.

Styling The Button

To begin, let's style up the .button and .button-text class.

.button {
    position: relative;
    padding: 8px 16px;
    background: #009579;
    border: none;
    outline: none;
    border-radius: 2px;
    cursor: pointer;

.button:active {
    background: #007a63;

.button__text {
    font: bold 20px 'Quicksand', san-serif;
    color: #ffffff;
    transition: all 0.2s;
Enter fullscreen mode Exit fullscreen mode

As you may have noticed, a lot of these properties are for look and feel - but the main one to focus on here is position: relative.

By using position: relative, it means we can center the loading spinner, which we'll see shortly.

Creating The Spinner

We'll be using the ::after pseudo-element to create the spinning animation. A pseudo-element is an element (like HTML) that you can style in CSS - in our case, ::after will create a "fake element" that sits inside our .button.

We're going to be applying CSS to a class called .button--loading. Basically, this is a modifier class on the .button which can be added dynamically through JavaScript whenever you want the spinning animation to appear. For example, this may be done at the time of submitting a form.

.button--loading::after {
    content: "";
    position: absolute;
    width: 16px;
    height: 16px;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    border: 4px solid transparent;
    border-top-color: #ffffff;
    border-radius: 50%;
    animation: button-loading-spinner 1s ease infinite;
Enter fullscreen mode Exit fullscreen mode

Let's focus on a few properties here:

  • content: ""; - this is a requirement to get the spinner to display
  • position: absolute; - used in combination with position: relative; above, and the top, left, right and bottom properties will allow us to center the spinner
  • border: 4px solid transparent - with this, we are setting a 4px wide solid border that is transparent. Combining it with border-top-color will only show a border at the top of the 16x16 square. This is key to creating a circle spinner.
  • border-radius: 50% - this creates the circle

I recommend you toggle some of these properties on and off, to get a full understanding of how they work to produce a circle.

As you may have noticed, we're also specifying an animation here, with a value of button-loading-spinner 1s ease infinite. This means, as long as the spinner is showing, make it spin infinitely with an ease timing duration, and an animation time of 1 second.

The button-loading-spinner animation doesn't actually exist yet, so we must create it.


To make the animation specified in the previous block of code above work, we need to create keyframes for it. This is simple.

@keyframes button-loading-spinner {
    from {
        transform: rotate(0turn);

    to {
        transform: rotate(1turn);
Enter fullscreen mode Exit fullscreen mode

Here, we're just saying the animation must turn our quarter-circle spinner from no turn to a full turn. With this code, the animation property above will now work.

Making The Button Work

Now that we've got all the CSS done, we need to make the spinner appear using JavaScript. Typically, you'll want to activate the spinner as soon as the button is clicked on.

To do this, you simply add the class of .button--loading, for example:

const theButton = document.querySelector(".button");

theButton.addEventListener("click", () => {
Enter fullscreen mode Exit fullscreen mode

Every application is going to be different, so it's up to you to decide when to toggle the loading spinner. To remove it, you can use classList.remove("button--loading");.


And that is how to create a button with a loading spinner using HTML and CSS. If you have any questions or comments please leave them below and I'll try my best to respond 🙂 cheers!

Discussion (0)