CSS pulse animation on hover

Create smooth looking pulse css animations for your website designs.

Apr 14, 2022 | Read time 9 minutes

🔔 Table of contents

In this post we will go over how to do pulse animation effect with CSS. Pulse animations can be used to give your interface a slick look and draw the user’s attention. They are commonly used with loading animations and sign up buttons.

What is a pulse animation?

Pulse animations can be seen in hamburger menus, sign up buttons or even thumbnails in a image gallery. These effects usually take shape of a smaller circle in the beginning of the animation and then expand as the animation progresses.

For example when the user hovers over the button, a pulse will show encouraging them to click the button. We can create pulse animation effects with CSS and with SVG images.

The key CSS property that can give us this effect is the transition:scale() function!

How to create pulse animation on hover

We create a basic circular button and and when hovered, it will give out a pulse effect. This will only require knowledge of CSS and @keyframes

To create the following effect, we use the following steps:

  • create a circular button using border-radius:50%
  • define the keyframes.

The HTML is very basic, we just have one div that is the container, and a span as the button.

<div class='container'>
  <span class='pulse-button'>Click me</span>

We can then style the button as the below. The button is circular so we need to use border-radius: 50%;. We also define the animation on hover - using the pulse keyframes and animating it for 1.5 seconds.

.pulse-button {
  position: relative;
  top: 50%;
  left: 50%;
  margin-left: -50px;
  margin-top: -50px;
  display: block;
  width: 100px;
  height: 100px;
  font-size: 1.3em;
  font-weight: light;
  font-family: 'Trebuchet MS', sans-serif;
  text-transform: uppercase;
  text-align: center;
  line-height: 100px;
  letter-spacing: -1px;
  color: white;
  border: none;
  border-radius: 50%;
  background: #5a99d4;
  cursor: pointer;
  box-shadow: 0 0 0 0 rgba(#5a99d4, .5);
.pulse-button:hover {
  animation: pulse 1.5s; /* Animate for 1.5 seconds on hover */

The @keyframes can be defined as below. The key idea is to start the animation with the button 85% of its initial size (smaller). As the animation progresses, we use the box-shadow property. This will give us a ripple effect behind our button when the user hovers. We will make the box shadow spread 50px and the colour to be blueish (#5a99d4).

As the animation finishes, we change the button back to its original size of 100% (scale(1)) and the box-shadow spread to be 0.

So the browser will fill in the keyframes, giving the impression that the button is growing slowly and its box shadow to expand - giving the pulsing animation effect.

@keyframes pulse {
  0% {
    transform: scale(.85);
  70% {
    transform: scale(1);
    box-shadow: 0 0 0 50px rgba(#5a99d4, 0);
    100% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(#5a99d4, 0);

👉 What is the CSS scale() function?

The scale() CSS function is the core of how to get this pulsating animation to work. As referenced in MDN https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scale the function scales a element along the 2D plane.

We can use this with the transform CSS property. When given the scale() function just one parameter - its treated like a percentage.

So a value of 1.2 (scale(1.2)) is treated like 120%. If we pass in two values such as scale(2, 0.5) this means that we scale it 200% on the x axis and 50% on the y axis:

.scale1 {
    transform: scale(1.2); /* Equal to scaleX(1.2) scaleY(1.2) - scale to 120% */

.scale2 {
    transform: scale(2, 0.5); /* Equal to scaleX(2) scaleY(0.5) - results in a stretched rectangular effect*/

Pulse loading animation with CSS

In the following, we will go over another example of a pulse animation - using it for loading animations. This is great use of pulse animations since it does not require much HTML and CSS and since it is a loading animation, we need to it render quickly.

The HTML is quite simple, just one div with a class of pulseLoader.

<div class="pulseLoader"></div>

Similar to the above example of a pulsating button on hover, to style our loading element, we need to make it circular so have to use the property border-radius: 50%;.

Keep in mind that since this div does not have any content, we have to explicitly define the width and height. I have just made it responsive and using 40vh. This just means that the div is 40% of the view height (width and height to be the same).

.pulseLoader {
  width: 40vh;
  height: 40vh;
  border-radius: 50%;
  background-color: white;
  outline: 1px solid transparent;
  animation: pulse 1.5s ease-in-out infinite; /* define to use the pulse animation keyframes and duration of 1.5 seconds and repeat infinitely */

Now to define the @keyframes, we just want the div to be scaled to 0% in size (not visible) in the begining of the animation and have a opacity of 0.8 (somewhat transparent).

As the animation progresses, the div will finish to be scaled to 100% of its original size and opacity of 0 (fully transparent).

This gives us the effect of a circular element growing but also disappearing as the animation progresses.

@keyframes pulse {
  0% { transform: scale(0); opacity: 0.8;}
  100% { transform: scale(1); opacity: 0;}

Browser support

Browser support for this type of animation is good across modern browsers such as chrome, firefox safari, etc. Even IE has support with a few edge cases (such as using the !important) keyword.

Animation performance

If performance is of a concern for your web design, then preferably we should use scale3d CSS function instead of the regular scale function. The scale3d function allows you to resize an element in 3D space and has the following signature:

scale3d(sx, sy, sz)

sx - representing the x-component of the scaling vector.

sy - representing the y-component of the scaling vector.

sz - representing the z-component of the scaling vector.

.scaled {
  transform: perspective(500px) scale3d(2, 0.7, 0.2) translateZ(100px);
  transform-origin: left;
  background-color: pink;

Using scale3d we can take advantage of hardware acceleration on our animation. The processing tasks will be offloaded from the main CPU an directed to the GPU. This can lead to performance improvements when you have lots of animations already or the user’s device is not of high spec.

Additionally offloading to the GPU will see less janky animations~

Final thoughts

In this post, we went through on how to create a pulse animation on hover effect with CSS. The key techniques that is required to create this effect is the tranform:scale() function and box-shadow. Pulse animations are usually circular so we also need to style the element as a circle with the border-radius:50% CSS property.

We use @keyframes to define the animation, with the start of the animation the scale the element to be smaller and then expand to its 100% size as the animation progresses to completion. To give an effect of a pulsating ripple, we define the element’s box-shadow to also spread and contract as the animation moves through its timeline.

As with any CSS animations, we need to consider browser support and fallbacks. This effect will be supported by most modern browsers (chrome, safari, firefox, etc) with the exception of IE 11 or lower with limited support.

Additionally animation performance is a consideration - using scale3d() instead of the regular scale() CSS function for hardware acceleration (offloading tasks from the CPU to the GPU to handle).

👋 About the Author

G'day! I am Huy a software engineer based in Australia. I have been creating design-centered software for the last 10 years both professionally and as a passion.

My aim to share what I have learnt with you! (and to help me remember 😅)

Follow along on Twitter , GitHub and YouTube