How to create high-performance CSS animations

This guide teaches you how to create high-performance CSS animations.

See Why are some animations slow? to learn the theory behind these recommendations.

Browser compatibility

All the CSS properties that this guide recommends have good cross-browser support.

transform

Browser Support

  • Chrome: 36.
  • Edge: 12.
  • Firefox: 16.
  • Safari: 9.

Source

opacity

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 2.

Source

will-change

Browser Support

  • Chrome: 36.
  • Edge: 79.
  • Firefox: 36.
  • Safari: 9.1.

Source

Move an element

To move an element, use the translate or rotation keyword values of the transform property.

For example, to slide an item into view, use translate.

.animate {
  animation: slide-in 0.7s both;
}

@keyframes slide-in {
  0% {
    transform: translateY(-1000px);
  }
  100% {
    transform: translateY(0);
  }
}

Use rotate to rotate elements. The following example rotates an element 360 degrees.

.animate {
  animation: rotate 0.7s ease-in-out both;
}

@keyframes rotate {
  0% {
    transform: rotate(0);
  }
  100% {
    transform: rotate(360deg);
  }
}

Resize an element

To resize an element, use the scale keyword value of the transform property.

.animate {
  animation: scale 1.5s both;
}

@keyframes scale {
  50% {
    transform: scale(0.5);
  }
  100% {
    transform: scale(1);
  }
}

Change an element's visibility

To show or hide an element, use opacity.

.animate {
  animation: opacity 2.5s both;
}

@keyframes opacity {
  0% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

Avoid properties that trigger layout or paint

Before using any CSS property for animation (other than transform and opacity), determine the property's impact on the rendering pipeline. Avoid any property that triggers layout or paint unless it's absolutely necessary.

Force layer creation

As explained in Why are some animations slow?, placing elements on a new layer lets the browser repaint them without needing to repaint the rest of the layout.

Browsers can usually make good decisions about which items should be placed on a new layer, but you can manually force layer creation with the will-change property. As the name suggests, this property tells the browser that this element is going to be changed in some way.

In CSS, you can apply will-change to any selector:

body > .sidebar {
  will-change: transform;
}

However, the specification suggests that you should only add this to elements that are always about to change. For example, this could be used for a sidebar the user can slide in and out. If the element doesn't change frequently, apply will-change using JavaScript when a change is likely to happen. Make sure to give the browser enough time to perform the necessary optimizations, and remove the property when the change has stopped.

To force layer creation in a browser without support for will-change, you can set transform: translateZ(0).

Debug slow or glitchy animations

Chrome DevTools and Firefox DevTools can help you figure out why your animations are slow or glitchy.

Check whether an animation triggers layout

An animation that moves an element using something other than transform is likely to be slow. The following example compares an animation using transform to an animation using top and left.

Don't
.box {
  position: absolute;
  top: 10px;
  left: 10px;
  animation: move 3s ease infinite;
}

@keyframes