DEV Community

Cover image for CSS Loading Animation - Morphing Icons Effect (clip-path, @keyframes)
crayoncode
crayoncode

Posted on

CSS Loading Animation - Morphing Icons Effect (clip-path, @keyframes)

Today let's get creative by building a morphing loading animation with icons having only 8 points and a few lines of CSS.

Read the full article or watch me code this on Youtube:

Result

Markup

This time we need almost no markup, as only a div.morph-loader is required, which is going to be shaped through a changing clip-path;

<div class="morph-loader"></div>
Enter fullscreen mode Exit fullscreen mode

Basic CSS

The basic CSS code is mostly about sizing the div and giving it some color. The animation is configured to run infinitely often and has a special cubic-bezier easing function that makes the clip-path quickly transition to the next shape and then maintaining the shape for a brief moment. So its quite steep in the beginning but then flattens out.

.morph-loader {
  display: inline-block;
  width: 12rem;
  height: 12rem;
  background: white;

  animation: 4s morph cubic-bezier(0.11,0.79,0.11,0.99) infinite;
}
Enter fullscreen mode Exit fullscreen mode

The animation itself

Now, for the animation itself it is simply a list of polygons whereas all polygon consist of exactly eight points. Only then the Browser can morph from one polygon to the next. Otherwise it will just "jump".

$path-octagon-small: polygon(
  37.5% 25%,
  62.5% 25%,
  75% 37.5%,
  75% 62.5%,
  62.5% 75%,
  37.5% 75%,
  25% 62.5%,
  25% 37.5%
);
$path-star: polygon(
  50% 0%,
  58% 42%,
  100% 50%,
  58% 58%,
  50% 100%,
  42% 58%,
  0% 50%,
  42% 42%
);
$path-shift-star: polygon(
  58% 42%,
  100% 50%,
  50% 50%,
  50% 100%,
  42% 58%,
  0% 50%,
  50% 50%,
  50% 0%
);
$path-thunder: polygon(
  60% 42%,
  80% 42%,
  40% 100%,
  38% 100%,
  55% 55%,
  35% 55%,
  60% 0%,
  80% 0%
);
 $path-triangle-1: polygon(
   25% 25%,
   75% 50%,
   25% 75%,
   25% 50%,
   25% 50%,
   25% 50%,
   25% 50%,
   25% 50%
 );
 $path-triangle-2: polygon(
   50% 25%, 
   100% 50%, 
   50% 75%, 
   50% 50%, 
   0% 25%, 
   0% 50%, 
   0% 75%, 
   50% 50%
 );

$clip-paths: (
  $path-octagon-small,
  $path-star,
  $path-shift-star,
  $path-thunder,
  $path-triangle-1,
  $path-triangle-2,
  $path-octagon-small,
);
Enter fullscreen mode Exit fullscreen mode

And finally, from that list, the @keyframes are generated dynamically. So first the step size is calculated and then the actual percentage is interpolated into the @keyframes rule. All that changes throughout each keyframe is simply the clip-path.

$step: 100% / (length($clip-paths) - 1);
$current: 0%;
@keyframes morph {
  @each $clip-path in $clip-paths {
    #{$current} {
      clip-path: $clip-path;  
    }

    $current: $current + $step;
  }
}
Enter fullscreen mode Exit fullscreen mode

Making it colorful

Since everything's greater with color, let's add some color transitions to each step. Therefore we need as many color codes as there are icons and we'll just add them to each keyframe:

$colors: (
  #d4aee0,
  #44abac,
  #b2dd57,
  #fdc82e,
  #8975b4,
  #2ca7d8,
  #d4aee0
);

$step: 100% / (length($clip-paths) - 1);
$current: 0%;
$i: 1;
@keyframes morph {
  @each $clip-path in $clip-paths {
    #{$current} {
      clip-path: $clip-path;  
      background-color: nth($colors, $i);
    }

    $current: $current + $step;
    $i: $i + 1;
  }
}
Enter fullscreen mode Exit fullscreen mode

And that's already it. Feel free to experiment with the shapes. If you want to create your own shapes, it's easy to use something like inkscape and a 100px x 100px canvas, so the coordinates already provide you with the correct percentages for the polygons.
Also bear in mind that the order of the points is quite important, as the first point of the previous polygon is directly interpolated into the first point of the next polygon. This can create awesome effects (e.g. from star to shift-star) or make it quite messy, but this is a pure matter of experimenting. The easiest way is probably to "roll" through the points, i.e. repeatedly move the first point to the end of the list or the other way round.

Top comments (0)