LOADERS

Pulse Loader

A clean animated loader with three pulsing dots. It works with pure HTML and CSS, so you can use it without JavaScript or extra libraries.

HTML
<div class="pulse-loader" aria-label="Loading">
  <span></span>
  <span></span>
  <span></span>
</div>
CSS
.pulse-loader{
  display:flex;
  align-items:center;
  gap:10px;
}

.pulse-loader span{
  width:14px;
  height:14px;
  border-radius:50%;
  background:#22d3ee;
  animation:pulseDot 1.2s ease-in-out infinite;
}

.pulse-loader span:nth-child(2){
  animation-delay:.15s;
}

.pulse-loader span:nth-child(3){
  animation-delay:.3s;
}

@keyframes pulseDot{
  0%,100%{
    transform:scale(.65);
    opacity:.45;
  }

  50%{
    transform:scale(1);
    opacity:1;
  }
}

How This Pulse Loader Works

The Pulse Loader is a CSS-only loading indicator built from one parent <div> and three empty <span> elements. Each span becomes a circular dot, and the three dots pulse at slightly different times to create a repeating loading sequence. The component does not use JavaScript.

The .pulse-loader container uses display: flex, so the three dots appear in a horizontal row. align-items: center keeps them vertically aligned, while a 10px gap creates equal spacing between each dot.

Every span is 14px wide and 14px high. The equal dimensions form a square initially, and border-radius: 50% turns that square into a circle. All three dots use the cyan background color #22d3ee.

Each dot runs the same pulseDot animation. The animation lasts 1.2s, uses an ease-in-out timing function, and repeats infinitely. Instead of moving the dots across the page, the animation changes their scale and opacity.

At the 0% and 100% points of the keyframes, each dot uses transform: scale(.65) and opacity: .45. This makes the dot smaller and partially transparent at the beginning and end of each cycle.

At 50%, the scale increases to 1 and opacity becomes 1. The dot therefore grows to its full 14px size while becoming completely visible. After reaching that midpoint, it gradually returns to the smaller, faded state.

The three dots do not reach their largest state at the same time. The first span has no extra delay, while the second span uses animation-delay: .15s and the third uses .3s. These staggered delays make the pulse travel from the first dot to the third instead of having all three expand together.

The ease-in-out timing function gives the scale change a gradual start and finish. This makes each pulse appear softer than it would with a constant linear speed. For more information about controlling animation timing, see the MDN CSS animation documentation.

Unlike a bouncing loader, this component does not change the dots’ positions. The animation is limited to scaling and opacity, so the loader remains compact and stable while still indicating ongoing activity.

The parent element also includes aria-label="Loading". This provides a simple accessible description for assistive technologies even though there is no visible text inside the loader.

Customizing the Pulse Loader

The Pulse Loader can be adjusted by changing a small number of size, spacing, color, and animation values in the existing CSS.

  • Change the 10px gap to increase or reduce the spacing between the dots.
  • Adjust the 14px width and height to make each dot larger or smaller.
  • Replace #22d3ee with another color to match your interface.
  • Change the 1.2s animation duration to make each pulse faster or slower.
  • Modify scale(.65) to control how small the dots become between pulses.
  • Adjust the .45 opacity value to make inactive dots more or less visible.
  • Change the .15s and .3s animation delays to alter the timing between the three dots.
  • Replace ease-in-out with another timing function if you want a different pulse rhythm.

Where to Use the Pulse Loader

This loader works well in interfaces that need a small indefinite loading indicator without displaying an exact completion percentage.

  • Form submission states while data is being processed.
  • Chat or messaging interfaces that need a compact activity indicator.
  • Dashboard cards waiting for remote content.
  • Modal windows during asynchronous operations.
  • Buttons or small controls that temporarily enter a loading state.
  • Cards, widgets, or panels where a simple horizontal loader fits naturally.

If you want a similar multi-dot loader with visible vertical movement, the Bouncing Dots Loader is a related CodeRipple component to consider. The Pulse Loader is better suited to layouts where you want the loader to stay in one position while still providing noticeable visual feedback.

Frequently Asked Questions

Does the Pulse Loader use JavaScript?

No. The component contains no JavaScript. Its complete effect is created with CSS animation, scale transforms, opacity changes, and staggered delays.

How does each dot create the pulsing effect?

The dots alternate between scale(.65) with .45 opacity and scale(1) with full opacity. This makes each dot appear to grow brighter and larger before shrinking again.

Why do the dots pulse one after another?

The second dot uses a .15s animation delay, while the third uses .3s. These delays offset the same animation and create the staggered sequence.

Can I make the pulse effect stronger?

Yes. Reduce the starting scale below .65 or lower the starting opacity below .45. A bigger difference between the inactive and active states will make the pulse more noticeable.

The Pulse Loader uses three simple dots, one shared keyframe animation, and small timing offsets to create a clean CSS-only loading indicator without any scripting.

Scroll to Top