Loading: Circle spinner

Matt Perry

In this tutorial, we're going to build the Loading: Circle spinner example step-by-step.

This tutorial is rated beginner difficulty, which means we'll spend some time explaining the Motion APIs that we've chosen to use (and why), and also any browser APIs we encounter that might be unfamiliar to beginners.

Here's a live demo of the example we're going to be creating:

Loading...

Introduction

The Circle Spinner example shows how to create a classic loading spinner using Motion for Vue. This simple yet effective animation continuously rotates a styled circle, providing users with visual feedback that content is loading.

Infinite rotation is achieved with a single animate prop:

:animate="{ transform: 'rotate(360deg)' }"

Get started

Let's start with the basic Vue component structure:

<template>
  <div class="container">
    <div class="spinner" />
  </div>
</template>

<style>
.container {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 40px;
  border-radius: 8px;
}

.spinner {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: 4px solid var(--divider);
  border-top-color: #ff0088;
}
<

The spinner is styled as a circle with a partially colored border, creating the classic loading indicator appearance.

Let's animate!

Import from Motion

First, import the motion component from Motion for Vue:

<script setup>
import { motion } from "motion-v"
</script>

Add the rotation animation

Now replace the static div with motion.div and add the animation:

<template>
  <div class="container">
    <motion.div
      class="spinner"
      :animate="{ transform: 'rotate(360deg)' }"
      :transition="{
        duration: 1.5,
        repeat: Infinity,
        ease: 'linear',
      }"
    />
  </div>
</template>

The :transition configuration:

  • duration: 1.5 - Each full rotation takes 1.5 seconds

  • repeat: Infinity - The animation loops forever

  • ease: 'linear' - Maintains constant speed throughout the rotation

Using linear easing is essential for spinners, as it prevents the animation from speeding up or slowing down, creating a smooth, consistent rotation.

Why use transform directly?

We're using transform: 'rotate(360deg)' instead of the shorthand rotate: 360. Animating the transform property directly enables hardware-accelerated animations, which run on the GPU rather than the CPU. This is especially important during loading sequences, as loading is typically a time of heavy CPU load. By offloading the animation to the GPU, the spinner remains smooth even when the main thread is busy. Learn more about web animation performance.

Conclusion

In this tutorial, we learned how to:

  • Create an infinitely rotating animation using the animate prop

  • Use repeat: Infinity to loop an animation forever

  • Apply linear easing for consistent rotation speed

  • Use transform directly for hardware-accelerated animations

This simple spinner pattern can be customized with different sizes, colors, and rotation speeds to match your application's design.

Motion+

Unlock all tutorials with Motion+

Unlock the full vault of 330+ Motion examples, premium APIs, private Discord and GitHub, and powerful VS Code animation editing tools.

One-time payment, lifetime updates.

Motion is supported by the best in the industry.