Spring easing SCSS mixin

This scss mixin adds support for spring easings using CSS linear() into your project.

Define the spring easing using the mixin and apply it to your CSS transitions.

Hover me

Installation

Copy the below scss mixin into your project:

@mixin spring-transition($mass, $stiffness, $damping) {
  transition-timing-function: linear(#{spring($mass, $stiffness, $damping)});
}
@mixin spring-animation($mass, $stiffness, $damping) {
  animation-timing-function: linear(#{spring($mass, $stiffness, $damping)});
}
@function envelope($time, $mass, $stiffness, $damping) {
  $omega: sqrt($stiffness / $mass); // Angular frequency
  $zeta: $damping / (2 * sqrt($mass * $stiffness)); // Damping ratio
  $exponent: -$zeta * $omega * $time;
  @return exp($exponent);
}

@function calc-spring($time, $mass, $stiffness, $damping) {
  $omega: sqrt($stiffness / $mass); // Angular frequency
  $zeta: $damping / (2 * sqrt($mass * $stiffness)); // Damping ratio
  $envelope: envelope($time, $mass, $stiffness, $damping);
  $cosTerm: cos($omega * sqrt(1 - pow($zeta, 2)) * $time);
  $sinTerm: sin($omega * sqrt(1 - pow($zeta, 2)) * $time);

  $springValue: 1 -
    ($envelope * ($cosTerm + ($zeta / sqrt(1 - pow($zeta, 2))) * $sinTerm));

  @return $springValue;
}

@function spring($mass, $stiffness, $damping) {
  $keyframes: ();
  $epsilon: 0.0001;
  $time: 0;
  $totalTime: 100;

  @for $i from 0 through $totalTime {
    $time: $i / $totalTime;

    $springValue: calc-spring($time, $mass, $stiffness, $damping);

    $keyframes: append($keyframes, $springValue);

    // break if the spring reaches equilibrium
    @if (abs($springValue - 1) < $epsilon) {
      @return $keyframes;
    }
  }

  $output: 0;
  $percentage: 0;

  @for $i from 1 through length($keyframes) {
    $percentage: ($i) * (100 / $totalTime);
    $output: $output + "," + nth($keyframes, $i) + " " + $percentage + "%";
  }

  @return unquote($output);
}

Usage

Apply the mixin to your CSS transitions:

.box {
  transition: transform 1s;
  @include spring-transition(10, 900, 80);

  &:hover {
    transform: scale(2);
  }
}

The mixin accepts three arguments:

  • Mass
  • Stiffness
  • Damping

More info

This mixin was created by Lochie Axon.

Check out easing.dev for more easing functions and their CSS implementations.

I hope you find this useful, thank you for your time.

Want to visualize your spring?

Try out the spring creator

Create a Spring