Product Design Lessons

Intro to Foundation  |   Lesson #103

Custom animations & transitions with Motion UI

Intro to Motion UI

Last week we reviewed how CSS animations and transitions work. As promised, this time we'll go into how Motion UI, our Sass based animation library, will help you add meaningful motion to your websites. We’ll learn how to add animations to a Foundation project and how to use Sass to write your very own animations & transitions.

We'll use a basic Foundation Compass project to set this up. If you have the Foundation CLI installed, run this command to create a blank project:


foundation new motion-ui

Open the folder in your command line with cd motion-ui, and in your code editor of choice.

This project already has Foundation built-in, but we need to add Motion UI as well. First, install it using Bower:


bower install motion-ui --save

Then open the file config.rb and add this line:


add_import_path 'bower_components/motion-ui/src'

Finally, add these lines to scss/app.scss:


@import 'motion-ui';
@include motion-ui-transitions;

Now when you run compass watch, your compiled CSS will include the built-in Motion UI transitions.

Transitioning Elements

Transitions allow us to animate in and out hidden or off-screen elements. Let's create a simple panel that can be transitioned in and out on click.

Start by adding this HTML to index.html. It's a click trigger and a hidden panel.


<a class="button" id="button">Toggle Panel</a>

<div class="panel" id="panel">
  <p>Lorem ipsum dolor sit amet!</p>
</div>

Now let's create a click trigger for the button, which will fire the appropriate transition, depending on if the panel is visible or not.

To start, we need to load the Motion UI JavaScript into the page. Add this <script> tag to the bottom of your page, after jQuery is loaded, but before app.js is loaded.


<script src="bower_components/motion-ui/dist/motion-ui.js"></script>

Open js/app.js and add this code:


var $button = $('#button');
var $panel = $('#panel');

$button.click(function() {
  if ($panel.is(':visible')) {
    MotionUI.animateOut($panel, 'fadeOut');
  }
  else {
    MotionUI.animateIn($panel, 'fadeIn');
  }
});

Let's break this down: first, we use click() to attach a click event listener to the button. Inside the listener's callback, we're checking to see if the panel is visible or not, using jQuery's is() function and special :visible selector.

If the panel is visible, that means we want to animate it out, so we call MotionUI.animateOut(). If the panel was not visible, that would mean we want to animate it in, and we would call MotionUI.animateIn(). Both animateIn and animateOut have two required parameters: the element to animate, and the transition class to add. Note that we used fadeIn and fadeOut. You can replace this with any of the built-in transition classes, or with your own custom transition class.

Now refresh the page in your browser, click the button, and you'll see it transition in and out.

Custom Transitions

Motion UI includes over two dozen built-in transition classes, but if you don't plan on using all of them, we recommend ditching the default CSS and using the Sass mixins instead. Otherwise, the default CSS will add a lot of extra weight to the page.

Every Motion UI effect is customizable. Let's replace the stock fade animation with a custom hinge animation.

Don't do the thing below yet. First, open scss/app.scss and comment out the @include we used to print the Motion UI CSS:


@import 'motion-ui';
// @include motion-ui-transitions;

To create a hinge, we'll use the mui-hinge() mixin. We need two classes: one for the in transition, and one for the out transition.


.hingeIn {
  @include mui-hinge(in);
}

.hingeOut {
  @include mui-hinge(out);
}

We'll start with the basics. Now open js/app.js and replace the fade transition classes with the new hinge classes:


var $button = $('#button');
var $panel = $('#panel');

$button.click(function() {
  if ($panel.is(':visible')) {
    MotionUI.animateOut($panel, 'hingeOut');
  }
  else {
    MotionUI.animateIn($panel, 'hingeIn');
  }
});

Refresh the page and you'll see the stock hinge animation. The hinge happens on the left edge, which looks a little odd. Let's fix the origin point, and also add some flair while we're at it.

Open up scss/app.scss, and let's add new parameters to the mui-hinge mixins (to make the code easier to read, we put each parameter on its own line):


.hingeIn {
  @include mui-hinge(
    $state: in,
    $from: top,
    $fade: true,
    $timing: map-get($motion-ui-easings, bounceInOut)
  );
}

.hingeOut {
  @include mui-hinge(
    $state: out,
    $from: top,
    $fade: true,
    $timing: map-get($motion-ui-easings, bounceInOut)
  );
}

Let's break down what we added here. $state, which we had before, defines if the transition is moving the element in or out. $from lets us set the hinge to swing from the top, right, bottom, or left edge of the element. $fade adds a fade that plays alongside the hinge. Lastly, $timing lets us bring in an easing effect. In this example, we're using a timing function custom to Motion UI, which gives the effect a slight bounce.

Save this file and then refresh your browser. Your hinge will now look all fancy. The above example only shows half the parameters that mui-hinge() accepts—refer to the Motion UI transition documentation to review the full list of effects, and how they can be customized.


Next Steps

If you're interested in exploring more of Motion UI, read up on series animations, which allow for the creation of composable effects. The library can also be plugged into Angular, React, or any other JavaScript library that supports state transitions. Review the configuration docs to learn how the library can adapt to other environments.

About the instructor

Geoff

Geoff is a designer and front-end coder at ZURB, and a member of the Foundation team. Within the ZURB office he's known for being an efficient coder and a Sass expert.