Guide

Example Animations

As explained on the using mixins guide page, Keyfram's mixins can be used can be used as functions and thus nested within other mixins. This feature of Keyfram let's you quickly compose complex animations that are difficult or impossible to accomplish using manual CSS keyframe specifications. This functionality is best illustrated by example so below are a few additional example animations making use of mixin composability.

Two sliding boxes coordinated to first join together, blink, and then reverse using kf-chain, kf-loop, and kf-reverse.

.slide-cross-blink {
  $slide-to-center: (
    '.a': (margin-left: (0ms: 0%,   1250ms: 50%)),
    '.b': (margin-left: (0ms: 100%, 1250ms: 50%)),
  );
  $blink-div: (
    '.b': (
      background: (0ms: white, 100ms: black, 200ms: white)
    )
  );

  @include kf-chain(
    $slide-to-center,
    kf-loop(4, $blink-div),
    kf-reverse($slide-to-center)
  );
}
.slide-cross-blink {
  $size: 20px;
  position: relative;
  width: 100%;
  max-width: 500px;
  height: $size * 2;
  div {
    position: absolute;
    width: $size;
    height: $size;
    border: 1px solid black;
  }
}
<div class='slide-cross-blink'>
  <div class='a'></div>
  <div class='b'></div>
</div>
Edit

Staggering bricks:

A more in-depth example showing how loops can be used to generate the inputs for kf-chain and kf-parallel. Also demonstrates kf-mirror, which runs the animation first in one direction and then in the opposite direction.

.staggering-bricks {
  $entry: (); 
  $lineup: ();
  @for $i from 1 through 18 {
    $entry: append($entry, ('div:nth-child(#{$i})': (
      0ms: (opacity: 0, margin-left: 0),
      200ms: (opacity: 1),
      500ms: (margin-left: 20px)
    )));
    $lineup: append($lineup, ('div:nth-child(#{$i})': (
      0ms: (margin-top: 0),
      400ms: (margin-top: if($i % 2 == 0, 0px, -20px))
    )));
  }; 

  @include kf-mirror(
    kf-chain(
      kf-stagger(-300ms, $entry...),
      kf-parallel($lineup...),
      ('div': (height: (0ms: 20px, 400ms: 60px)))
    )
  );
}
.staggering-bricks {
  position: relative;
  height: 40px;
  margin: 30px 0;

  div {
    // common properties
    width: 20px;
    height: 20px;
    content: " ";
    position: absolute;
    opacity: 0;
    box-sizing: border-box;
    border: 1px solid transparent;
    margin-top: 0;

    &:nth-child(odd) {
      top: 20px;
    }
  }
}

$base-color: #D6FFAD;
$n-bricks: 18;

// prep map
@for $i from 1 through $n-bricks {
  .staggering-bricks div:nth-child(#{$i}n) {
    background: darken($base-color, $i * 5);
    left: -40px + 20px * $i;
  }
}
<div class='staggering-bricks'>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
    <div></div>
</div>
Edit

Playing with timestretches and easing:

An example showing how kf-ease and kf-stretch can be used to manipulate the easing and timing respectively of pre-built animations.

.combining-mixins-example {
  $joiner: (
    0ms: (
      'div.a': (left: -10px, top: -10px),
      'div.b': (left: 10px, top: -10px),
      'div.c': (left: -10px, top: 10px),
      'div.d': (left: 10px, top: 10px)
    ),
    1000ms: ('div': (left: 0, top: 0))
  );
  $darken: (
    0ms: ('div': (background: transparent)),
    800ms: ('div': (background: #e8e8e8)),
    1600ms: ('div': (background: black))
  );
  $slide: ('div': (margin-left: (0ms: 0px, 1s: 100%)));

  @include kf-chain(
    $joiner, $darken, $slide,
    kf-reverse($joiner),
    kf-stretch(2, $joiner),
    kf-ease(ease-in-out, kf-reverse($slide)),
    kf-stretch(0.2s, kf-loop(10, kf-mirror(kf-reverse($darken)))),
    kf-reverse($joiner),
    kf-reverse($darken)
  );
}
.combining-mixins-example {
  height: 40px;
  width: 100%;
  position: relative;

  div {
    $s: 10px;
    position: absolute;
    width: $s;
    height: $s;
    border: 1px solid black;

  }
}
<div class='combining-mixins-example'>
  <div class='a'></div>
  <div class='b'></div>
  <div class='c'></div>
  <div class='d'></div>
</div>
Edit

Rotating box:

An example making use of the animating the transform property using kf-chain.

.rotating-box-example {
  $spin-animation: (
    transform: (
      0ms: rotate(0deg, 0deg),
      1500ms: rotateY(360deg) rotateX(360deg),
    )
  );
  $fade-out: (
    background: (
      0ms: white,
      600ms:black
    )
  );

  @include kf-chain(
    $spin-animation,
    kf-mirror($fade-out)
  );
}
.rotating-box-example {
  position: relative;
  transform-style: preserve-3d;

  $n-width: 3;
  $n-height: 3;
  $n-z: 3;
  $size: 10px;
  width: $size * 2;
  height: $size * 2;


  div {
    position: absolute;
    width: $size * 2;
    height: $size * 2;
    border: 1px dotted black;

    &:nth-of-type(1) {
      transform: translateZ(-$size) rotateY(180deg);
    }
    &:nth-of-type(2) {
      transform: rotateY(-270deg) translateX($size);
      transform-origin: top right;
    }
    &:nth-of-type(3) {
      transform: rotateY(270deg) translateX(-$size);
      transform-origin: center left;
    }
    &:nth-of-type(4) {
      transform: rotateX(-90deg) translateY(-$size);
      transform-origin: top center;
    }
    &:nth-of-type(5) {
      transform: rotateX(90deg) translateY($size);
      transform-origin: bottom center;
    }
    &:nth-of-type(6) {
      transform: translateZ($size);
    }
  }
}
<div class='rotating-box-example'>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>
Edit