Framer, Modules, Prototype
Prototyping Material Design with Framer

Prototyping Material Design with Framer

Material design is a design language developed by Google that’s big on responsive animations, transitions, and the use of lightning and shadows to provide depth. In this Framer tutorial, we’ll look at how to prototype some common material design interactions.

Here’s what we’ll prototype:


To get started, download the zip file and unzip the Sketch file. 

The design contains two artboards for the home screen and the upload screen. The navbar and statusbar are hidden in the home screen because we’ll make them global for both our screens in our prototype.


With Framer Studio open, update the device to display a Nexus 5 by clicking the Viewer button at the far right of the toolbar.  


With our saved Sketch file open, we can import it by clicking the Import button on the toolbar or using the shortcut Command+i. With the Import dialog open, we should see the Import button active with our file name under the Sketch heading. Click the button and our design should appear in the preview pane.


Framer automatically adds a line of code and assigns all the imported layers to a variable.

We’ll use the utility function globalLayers on our imported layer to enable accessing all layer groups by their name. 

Now instead of having to type something like superheroMaterialLayers.navbar, we only have to type navbar.

To display the statusBar and navbar and make it persistent on both screens, we’ll set their superLayer to the device.

Because we’re going to want to add a ripple when the floating action button (FAB) is pressed, we’re going to hide the image layer we imported from our Sketch file and create it with Framer. To hide the existing layer, we’ll set its visible property to false.

To create our FAB, we’ll select the layer in Sketch to view the properties and match them in our new layer. To make it in the shape of a circle we’ll set the border radius to be 50%. 


We’ll need to add the plus sign to our newly created FAB. We can do that by specifying its superLayer to be our FAB and then centering it using the center function.

Our initial home screen is now ready.


Before we move on to prototype the interaction, let’s set up the upload screen.

When we import multiple artboards with Framer, only the first one is visible. To view the upload screen, we’ll need to first set its visible property to true. 

You’ll notice that the FAB is on top of the screen because we created it after we imported the layers.


We want the upload screen to be on top. To do that, we can use the placeBefore method to specify the layer order.

Another way we could have done this is to do the opposite and use the placeBehind method.

The last thing we need to do to the upload screen is create a hit target for the back arrow. We’ll create a circle layer and overlay it on top of the arrow. This layer will also act as a superlayer when we add our ripple effect.

Here’s how it looks:


Once we have it where we want it, we’ll set its background color to null or transparent to hide it. We’ll also set the superLayer to the form so when the form animates, the overlay will move along with it.

We’re now ready to move on to our material design animation states and options.

Our Framer prototype will have two states — the default state and the upload state. The default state is already defined by the initial state of the layers.

Since we want the list of superhero’s as our initial screen, we’ll need to first overwrite the current default state of the upload screen since we don’t want it showing initially.

To set properties for a state, we’ll type the layer name, followed by a period, the keyword states, another period, and then add. We’ll then indent with the state name followed by a colon. On the next line, we’ll indent again and specify the properties for our state.

For the form layer, we’ll place the y position at the bottom of the screen for its default state. For the upload state, we’ll set it to its current y position.

For the keyboard, we’ll place its initial y position behind the navbar. For the upload state, we’ll set it to its current y position.

We’ll create an array with these layers (we’ll add more layers later) so we can easily loop through each one and set their states. We create an array by putting the contents in between square brackets.

Now let’s loop through these layers and set their state to the default state. We’ll use the switchInstant function so it switches without animating.

We now see our initial list screen. Let’s add states for layers on this screen.

When we click the floating action button, we’ll want to rotate and hide the add icon. We can set the rotation and opacity property for the upload state.

We won’t need to define the default state for the button since the initial state is what we want.

For the floating action button, we’ll want to increase the width and height so it covers the top half of the screen. Since it’s a circle, we’ll need to set the x and y positions off screen and have a circle bigger than the screen width. This is just a matter of trial and error until you have something that looks right. We can also give it a larger shadow.

Let’s go back to our array we created earlier and add in these two layers.

To test this, create a click event for the FAB. We create a click event by typing the layer name, followed by a period, “on” to listen, and then the click event to listen to. We can use Events.Click or the shortcut of just “click” in lowercase and quotes.

We’ll then add our indented block of code that we want to run under this line. We’ll want to switch our layer states to the upload state. We can do this by creating a for loop that goes through each item in our array and uses the switch function to change states.

Let’s test out our prototype to see it in action. 


It looks pretty good but is really slow so let’s adjust the default animation time and curve, along with any other animation options.

We’ll set our default curve to match the material design guidelines. Framer provides a few pre-defined curves like “ease-in” and “ease-out”. For material design, we’ll be using custom bezier-curves.

When something already exists on screen and moves to another position on screen, we want 40% out of first frame and 80% into second frame. The curve would be defined like this:

This would look like this:

bezier-curve 1

When something comes from offscreen it has 0% out of the first frame and 80% in on the second frame:

Here’s how this one looks:

bezier-curve 2

When something leaves the screen it has 40% out of the first frame and 0% in on the second frame:

Here’s the curve:

bezier-curve 3

We can set our default curve by setting the Framer.Defaults.Animation property.

We’ll set it to the curve when something already exists on screen and moves to another position on screen. We’ll also give it a time of .5 seconds.

If you try the animation now, it’s a little better but we can’t really see the add icon rotate, the form appears a little fast, the keyboard shouldn’t come up right away, and the indicator should blink. 

We’ll set the animation options for the FAB button, form and keyboard to have a slight delay. To set the animation option for individual layers, we can type the layer name, followed by a period, and then states.animationOptions

For the indicator, we’ll need to first give it some states. For the default state, we’ll want to set the opacity to 1. For the upload state, we’ll set it to 0.

For our animation option, we’ll give it a delay and give it a high repeat value so it repeats going from an opacity of 1 to 0. 

We’ll need to remember to place it in our materialLayers array.

Now when we try our prototype, we see the slight delays and the blinking indicator when going to the upload screen.


Let’s also prototype tapping the back button. We can create a click event and loop through our array like we did for the floating action button, except this time switch to the default state.

We don’t need to see the animation of the FAB button and add icon when going back, so above our for loop, switch to the default state without animation using switchInstant.

Since we’re leaving the screen, we’ll need to adjust our curve to match the material design guideline. We’ll also make it a little faster. We can do this in our switch statement – don’t forget the comma after the “default”:

To improve on this prototype and make it more like material design, we can add a ripple effect when we tap the buttons. 

Since we’ll need to create the ripple for both the FAB and the back button, it makes sense to create a function so we can call it from both click events.

To create a function, we type the name followed by an equal sign, and any arguments in parenthesis, followed by an arrow sign. We’ll want to pass in the click event information so we know where the button was clicked along with the layer.

Within our function, we’ll create a new layer called ripple. We’ll set the borderRadius to 50% so it will be a circle and will start the scale at 0 and opacity at .5. We’ll give it the same width and height of the button.

We’ll also give it a background color of white, set it’s brightness and set the its superLayer to the layer we’re tapping on.

We want the ripple to only appear within our circle. To do that, we need to set the force2d property to true. This enables advanced masking, like having a mask with rounded corners.

Finally, we need to set the point where we start the animation. When we have a click event, event information is passed along in a variable called event.

The event contains information like where the tap or click took place. This is accessed by the offsetX and offsetY properties.

Now that we’ve created our ripple layer, we can animate it. We animate by typing the layer name followed by a period, and then the animate keyword. On the next line, we indent and type properties followed by a colon.

We want the ripple to fade away so we set the opacity to 0 and will double the scale

We’ll also update the curve to be an “ease-out”, which starts fast and slows towards the end.

After our animation ends, we’ll want to remove the ripple layer. We can listen to the Events.AnimationEnd event on the ripple layer. A shortcut to this event is just “end”.

When we detect the animation end, we can call the destroy function on the layer to remove it.

All that’s left to do is to call the function within our click events. We’ll pass in the event information, along with the layer. Instead of typing the layer, we use the shortcut this, which is the layer we’re listening to.

We’ll also do this to the back button click event.

If you try out the prototype, tapping the back button to go back to the default view happens too fast that we don’t see the ripple effect. We can add a slight delay using the delay utility function to make sure we see this briefly. To use the delay utility, type Utils.delay followed by the number of seconds to wait, and then the arrow sign. We’ll then indent our code underneath it.

Here’s our finished prototype.


You can check out the prototype and download the project here:

Material Design with Framer

We only scratched the surface with material design. If you’re interested in learning more, I’ve put together a list of prototypes that others have done that use material design, as well as some Material Design modules that you can use in your own prototypes.

Material Design Framer Prototypes

Material Design Framer Modules

What Framer tutorials do you want to see? Leave a comment below or share your thoughts with me on Twitter (@kennycheny). If you haven’t already, join the mailing list so you won’t miss any upcoming Framer tutorials.

Want more Framer content like this?

Share this Story

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

About Kenny Chen

Hi, I'm Kenny - a UX Designer from Los Angeles who believes that beautiful, subtle movement enhances the user experience and makes products more engaging, dynamic, and memorable. My goal with Prototyping with Framer is to help you design amazing interaction and animation prototypes.