Go to Framer X ›


This section will show you how to use code to create interactions in Framer. You’ll also get a few simple pointers on setting yourself up for success.

No matter what your background, we’ve designed Framer Code to be a fun and rewarding tool. For beginners, a familiarity with HTML, CSS or Javascript helps, but a desire to learn is just as important. Thousands of designers — most with no coding background — have started Framer and gone on to create amazing work, using it as a tool to level up in their careers. Over time, we’ve used their experience to develop a simple strategy to get you started with Framer.

Briefly skim through this guide to familiarize yourself with concepts, but don’t feel like you need to thoroughly understand everything before getting started. We’ve developed Framer as a conceptual learning tool. To that end, we’ve added many features that are designed to help lower the learning curve to code. From simplified language and Auto-Code to intuitive error messaging and in-app documentation, Framer guides you as you go.

If you’re familiar with the basics, check out our programming guide on how to express more complex behavior like logic, variables and loops.


There are three main ways to begin adding interaction in Framer. In this guide, we teach you about the relationship between our Code and Design modes, how to import from an external graphics tool and how to add a layer using code.

For an optimal Framer workflow, we recommend you set up your designs directly in the Design tab. You can draw directly on the canvas or use device-specific Frames. Framer Design has been optimized for code-based interaction design work so it is highly intuitive and responsive. Hierarchy, layout and grouping in Design have been programmed to work seamlessly with our Code mode. When you’re finished with Design, simply toggle on the target icon for any layers you want to animate, switch over to Code mode and begin adding interactions.

About targeting ›

Another way to use Framer is to import your designs from Sketch, Figma and Photoshop. You can import any grouped layers, add animations in Code and then switch back to your favorite graphics tools and make changes as needed. We offer full-integration, so this workflow can be as seamless as a few clicks.

About importing ›

Lastly, you may add layers directly by typing layerA = new Layer directly into the code editor. While we don’t recommend this workflow, it may come in handy in instances when you want to use Framer for quick concepting or ideation.

Preview Window

On the code side of Framer, you’ll see a preview window that gives you real-time visual feedback on any changes you make in Code or Design. You can also drag, drop and resize layers directly in this window.

Framer’s preview window offers real-time feedback on designs made in either the Design or Code tab. To replay animations, simply hit CMD + R to reload. The window snaps to the chrome but can be completely detached for a larger workspace. To view your design on multiple screens, simply select from the dropdown menu of devices in the top navigation bar of the preview window.

If you created your design directly on the canvas in Design, all of the layers you insert will not contain a parent Frame. Placing your layer on the x: 0 and y: 0 position values will position the layer to the top left of the preview window.


Frames are more than placeholders. They have been engineered to account for responsive device work.

From the get-go, we prompt you to select the device you’re designing for. Choose from a full spectrum of watch, mobile, computer, tablet, and TV devices. After you select your device of choice, Framer instantly adapts the preview in the code tab. You can change this at any time by selecting a different device from the preview window dropdown.

Design to Code

Your designs made in Frames get translated perfectly into code. Every Frame is automatically set up to be the parent of all the layers placed in the Frame. Targeting a Frame in the code will automatically also target all of its child layers. This will make setting up interactions like a FlowComponent easier than ever.

# Initialize FlowComponent 
flow = new FlowComponent
#  Set up a flow from your Frames 
FrameA.onClick ->
FrameB.onClick ->


If you’ve ever used a visual design tool, you’ll already be familiar with the concept of a Layer. Without content, it’s simply a rectangle. But it can contain an image, a video, audio, text, and much more.

Inserting & Targeting

Inserting a layer is as simple as drawing something in the design tab and switching back to the code.

When you have set up your layers in the design tab and made the layers you want to target targetable, you are ready to start coding. To target a layer you have designed directly in Framer simply insert its name followed by the behaviour you want to add to it.

#  Target and animate a layer from your design 
    y: 200
        time: 1
        curve: Bezier.ease


The layers you design in Framer have many types of properties. Ones that define its position, appearance and if you decide to add them in code, interactivity. All of these properties can be overridden directly with code. For example, you can define a red background, but override this with blue in code.

# Background layer override 
background.backgroundColor = "#28affb"

A layer has a ton of visual properties. You can transform it, scale it, hide it and more. After having created a layer, in design, you can still override these properties in code.

# Override properties 
layerB.borderRadius = 4
layerB.rotation = 45
layerB.opacity = 0.5
layerB.scale = 0.5

A great way to explore all layer properties is by using Auto Code. When switching from the design tab simply click animation and select your desired layer. The Auto Code panel will automatically show up for you to drag around the layer directly in the preview window and edit its value.

In front of every layer you start to Auto Code, an edit icon appears. Click this to bring up the properties panel. For a list of all layer properties, check out our Docs.


A layer can be positioned with its x and y properties. These values define the distance from the top-left corner of the canvas.

# Position layerA 
layerA.x = 200
layerA.y = 200

Layers can also be positioned using dynamic properties. Say you want to position one layer relative to another. Instead of manually calculating the center point of this layer, you can simply use the midX and midY properties. You can find all positioning properties in our Docs.

# Align to center of the x axis of layerA 
layerB.x = layerA.midX
# Align to center of the y axis of layerA 
layerB.y = layerA.midY

You can center a layer within its parent by using the Align property. Parent - child relationships are defined in the design tab but can easily be overridden in code. Layers can also be exclusively centered horizontally or vertically. See below for all available Align properties.

  • Align.left (x)
  • Align.right (x)
  • Align.top (y)
  • Align.bottom (y)
  • Align.center (x and y)
# Define layerA as the parent of layerB 
layerB.parent = layerA
# Align layerB to the bottom right of its parent 
layerB.x = Align.right
layerB.y = Align.bottom


Aside from grouping layers in the design tab layers can also be grouped directly in code. A layer placed within another layer is called a child layer. The container layer is called the parent layer. Layers inherit properties from their parent layers, like their opacity or position.

# Two ways to define hierarchy 
layerB.parent = layerA

If you want to place a layer in front of another layer, you can use the placeBefore method. Vice versa, you can use placeBehind.

layerA = new Layer
layerB = new Layer
# Place layerB on top 

Layer Types

Layers can be almost anything. Think backgrounds, images, videos, text and more. In the design tab you can add all of the standard layers. Code allows us to insert interactive elements into our design like video and audio. To add a video, for example, simply drag and drop the video into the code editor.

# Video 
video = new VideoLayer
    video: "fish.mp4"

Text Layers

Framer allows you to add text directly to your design. To make the text interactive or change the text itself or its color, you can insert a TextLayer from the code tab. Text layers have unique text styling properties. The width and height are automatically calculated and set, depending on the text and its style.

# Create text layer 
title = new TextLayer
    text: "Hello!"

Most of the text styling properties are inherited from CSS. You can find all of these properties and more in our Docs.

# Create text layer 
title = new TextLayer
    text: "Hello!"
    fontSize: 64
    fontWeight: 600
    x: Align.center
    y: Align.center

You can use powerful templating to manipulate and animate specific parts of your text. To set values for template tags wrap text in { }.

# Create text layer with template tag. 
layerA = new TextLayer
  text: "{speed}KM/h"
# Set speed template tag value. 
layerA.template =
  speed: 50
# Shorthand for when there’s only one tag. 
layerA.template = 50
# Both result in "50KM/h". 

You can also use template tags to format and calculate various values.

# Create text layer with template tags. 
layerA = new TextLayer
    text: "{speed}{unit}/h"
# Format template value to only have 2 decimals. 
layerA.templateFormatter =
    speed: (value) ->
# Animate template value from 0 to 100. 
        speed: 100
        unit: "KM"

For single tags, use the following shorthand.

# Format template value to only have 2 decimals. 
layerA.templateFormatter = (value) ->


Almost every layer property can be animated. Multiple properties can be animated at once. You can then continue to define the curve, time, delay and many more custom animation options.

Get Started

Let’s start by animating the opacity of a layer. You can start animations by using the animate keyword, and then defining a set of properties.

    opacity: 0.5


You can completely customize the feel of your animation, by changing options like time, curve and delay. Below is a list of the available options:

  • time (in seconds)
  • curve (Bezier, Spring)
  • delay (in seconds)
  • repeat (amount of times)
  • colorModel (rgb, hsl, husl)

Durations in Framer are defined in seconds. Add animation options by using the options keyword, and indenting its properties.

# Animate with an easing curve 
    rotation: 180
    borderRadius: 200
        curve: Bezier.ease
        time: 1

Easing Curves

Animations optionally take a curve that describe the type of animation. You can use pre-defined curves like Bezier.linear or Bezier.ease. The Bezier.ease curve is the default in Framer. See all built-in easing curves below, or check out this website to learn more.

  • Bezier.ease
  • Bezier.easeIn
  • Bezier.easeOut
  • Bezier.easeInOut
# Animate with an easing curve 
    scale: 0.75
        curve: Bezier.ease
        delay: 0
        time: 1

Spring Curves

To make animations that feel truly native, you’ll want to work with spring curves. The bounciness of our spring curve can be customized with damping and it can be used along with the time property.

# Animate with a spring curve 
    scale: 0.75
        curve: Spring(damping: 0.5)
        time: 0.5


States allow you to define the different appearance options of a layer. A layer can have multiple states, each with a different set of properties. States can then be cycled through, with or without animation.

Adding States

Think of states as a different way to manage multiple animations. You start by adding the states, and then animate or cycle between them.

In the example below, layerA is set to 100% opacity in the design tab. Next, a new state for layerA is defined, titled "fade", with an opacity set to 0.

# A new state titled "fade" 
layerA.states.fade =
    opacity: 0

For layerA to inherit the properties of the "fade" state, it needs to switch from the default state to the "fade" state.

# Animate to the state 
# Instantly switch to the state 

Cycling States

States can also be cycled between, using stateCycle(). Just like with layer animations, you can also add animation options to states.

# Add states and animation options 
layerA.states.rotate =
    rotation: 180
        time: 1
        curve: Bezier.ease
# Cycle between states 
layerA.onTap ->

Editing States

To override states, simply add a new state with the same name.

# Override third state 
layerA.states.rotate =
    rotation: 180


Events are things that can happen to layers, often triggered by user interaction. With events, you can animate layers based on these interactions. From simple taps and swipes to advanced multi-touch gestures.

Framer includes a ton of events. The most common ones you may be familiar with, onTap and onScroll. Events can also be caused by animations, state switches, page changes and the like. And if you want to design more complex interactions, you can use the multi-touch gestures, like onEdgeSwipe and onPinch.

layerA.onTap ->
layerA.onScroll ->
layerA.onSwipe ->
layerA.onAnimationEnd ->

One of the most common use cases of events is toggling between a set of states on tap (which is click or touch).

# Toggle states on tap 
settings.onTap ->

Example: Animation Chaining

Events can be used to chain animations. For example, you can start a new animation after another one ends by listening to the AnimationEnd event.

# Animation Events 
layerA.onAnimationStart ->
layerA.onAnimationEnd ->

Below is a simple example of a chained animation. Every animation gets an AnimationEnd event, so they can be chained infinitely.

    x: 80
        curve: Bezier.ease
layerA.onAnimationEnd ->
        x: 0
            curve: Bezier.ease


Draggable layers include physics and many customizable properties that open up new creative possibilities. By accounting for things like the speed and the direction, you can take greater control over dragging interactions.

Get Started

Let’s start by creating a draggable layer. Simply set draggable.enabled to true. Now, you can pick it up, place it elsewhere, and toss it around.

You can also restrict the dragging direction, by disabling dragging horizontally or vertically. Both are enabled by default. You can also specify the speed. This provides accelerated or reduced dragging.

# Make the layer draggable 
layerA.draggable.enabled = true
# Prevent vertical dragging 
layerA.draggable.horizontal = true
layerA.draggable.vertical = false
# Alternative way by setting the speed 
layerA.draggable.speedX = 1
layerA.draggable.speedY = 0


In most cases, you’ll want to limit the range a layer can be dragged within. For example, think of the pull-to-refresh gesture, in which you can only drag a certain distance. This can be achieved with constraints. Constraints have x, y, width and height properties. Think of it as another layer, that contains your draggable layer.

# Make the layer draggable 
layerA.draggable.enabled = true
# Set the constraints frame 
layerA.draggable.constraints =
    x: 0
    y: 0
    width: 160
    height: 80

Overdrag, Bounce and Momentum

It’s likely you’re already familiar with these terms, even if you don’t know them by name. Let’s have a look at each of them. A draggable layer can be dragged beyond its constraints, although it will snap back. This is called overdrag. Think of Safari on iOS, where you can drag websites beyond the top and bottom of the pages. When a layer is moving in a direction, it can also bounce beyond its constraints. This is called bounce. It’s sort of like a rubber-band effect. Finally, setting momentum to false disables the default physics of your draggable layer. You can still move it, but you can’t toss it around anymore. The momentum and bounce properties can also be customised. Have a look at this example of a custom draggable layer with constraints.

# Disable overdrag 
layerA.draggable.overdrag = false
# Disable bounce 
layerA.draggable.bounce = false
# Disable momentum 
layerA.draggable.momentum = false


The three fundamental dragging events that you can listen to are: DragStart, DragMove and DragEnd. The Move event is fired whenever the draggable layer is moving. Unlike the DragMove event, this includes the momentum and bounce animations.

# Start dragging 
layerA.onDragStart ->
        scale: 1.1
# After dragging 
layerA.onDragEnd ->
        scale: 1

Drag Animation

There are two specific events that occur when momentum and bounce are enabled: DragAnimationDidStart and DragAnimationDidEnd. They occur after DragEnd, while the layer is animating.

# After DragEnd, the DragAnimation starts 
layerA.onDragAnimationStart ->
        scale: 0.8
# Starts with the momentum and bounce 
layerA.onDragAnimationEnd ->
        scale: 1


Pinchable layers can be scaled and rotated with two fingers. This multi-touch gesture is often seen in maps and photo apps, to zoom and navigation content.

In Framer for Mac, you can hold the alt key while moving your cursor to bring up a second cursor. This allows you to emulate multi-touch gestures. Just like with draggable layers, you can enable pinching by setting pinchable.enabled to true.

layerA.pinchable.enabled = true

Pinchable layers contain scale and rotate properties, both enabled by default. By disabling the scale, you can only rotate a pinchable layer, and vice versa.

# Disable scale on pinch 
layerA.pinchable.scale = false
# Disable rotation on pinch 
layerA.pinchable.rotate = false

Pinch Events

The three basic pinchable events are: onPinch, onPinchStart and onPinchEnd. Let’s have a look at the last one. Pinching adjusts the actual scale and rotation properties of a layer. So after a pinch, we can animate these properties back to their default values.

# Enable pinching 
layerA.pinchable.enabled = true
# Animate back to original position 
layerA.onPinchEnd ->
        scale: 1
        rotation: 0
            curve: Spring(damping: 0.5)
            time: 0.5


If you enable both dragging and pinching, the layer also becomes pannable. Panning is the same as dragging, except it’s a multi-touch gesture. You can detect a pan with the onPan event.

# Enable panning 
layerA.draggable.enabled = true
layerA.pinchable.enabled = true
# Animate back to original position 
layerA.onDragEnd ->
        scale: 1
        rotation: 0
            curve: Spring(damping: 0.5)
            time: 0.5


Think of a component as a bundle of layers, with pre-defined interactions. Like the SliderComponent, which allows you to add sliders without having to create all the elements from scratch. They’re completely customizable, but work out of the box.

Framer includes the following Components. Read more on the Flow, Scroll, Page and Slider Components in the sections below.

  • FlowComponent
  • ScrollComponent
  • PageComponent
  • SliderComponent
  • RangeSliderComponent
  • MIDIComponent


The FlowComponent helps you quickly transition between multiple screens. It’s especially useful for turning static screens into fully interactive flows.

What’s unique about the FlowComponent is that it knows which screen you’re viewing. It keeps track of your history, allowing you to navigate back-and-forth at any time. By default it features detailed, native-feeling transitions. When switching screens, the current screen automatically animates out of view. And when adding an overlay like a modal dialog, the background gets a semi-transparant dark overlay, too.

Lets start by adding a layer to the FlowComponent. This works much like adding layers to the PageComponent, and can easily be done by using the showNext function. The first layer you add doesn’t get animated.

# Create FlowComponent, show layerA 
flow = new FlowComponent

Switching Screens

You can use the showNext function to transition to the next screen.

# Create FlowComponent, show layer 
flow = new FlowComponent
# Switch screens on click 
layerA.onClick ->

Framer keeps track of which screen you’re currently viewing. You can switch back to the previous screen with the showPrevious function.

# Switch to next screen 
layerA.onClick ->
# Switch to previous screen 
layerB.onClick ->


With one of the showOverlay functions, you can overlay any layer. The current screen gets a semi-transparent dark background. This is most noticeable when overlaying a smaller layer, like a sidebar or an action sheet. You can specify one of the following directions:

  • showOverlayCenter
  • showOverlayTop
  • showOverlayRight
  • showOverlayBottom
  • showOverlayLeft
# Create FlowComponent 
flow = new FlowComponent
# Modal and button are set up in the design tab 
# Switch back 
button.onClick ->


Any child layer that exceeds the height or width of the FlowComponent automatically becomes scrollable. It will be vertically scrollable if it’s taller, and horizontally scrollable if it’s wider. You can target this scrollable layer with flow.scroll. All scrolling properties and events can be used.

Layers positioned at the top or bottom of the Frame will be recognized as headers and footers, like a tab or navigation bar. Remember that your Frame has to exceed the height of the device frame to make this work.

To add a fixed footer or header to the FlowComponent, you can use the header and footer properties. This will anchor them to the top or bottom of your device screen, even when transitioning to the next screen.

# Set a fixed navigation bar (on top) 
flow.header = flowBar
# Set a fixed tab bar (on bottom) 
flow.footer = tabBar

Scrolling Example

Check out the example below to see how a Frame from Design automatically becomes scrollable, along with a fixed header and footer.

Open Example ›


You’re probably familiar with the smooth scrolling on iOS. Getting this to feel just right involves a lot of physics. The ScrollComponent in Framer takes care of this for you, while remaining completely customizable.

A ScrollComponent is built with two layers. First, the ScrollComponent itself, which serves as a masking layer.

Second, the content layer, which has draggable enabled and pre-defined constraints. The size of the content layer is calculated for you, based on the size of its children.

# Create a ScrollComponent 
scroll = new ScrollComponent
    size: 120
# Assign the content layers 
layerA.parent = scroll.content
layerB.parent = scroll.content

Similar to draggable layers, you can also restrict the scrolling direction.

scroll.scrollHorizontal = true
scroll.scrollVertical = false


A great way to bring your static designs to life in Framer is by using scrolling. To add scrolling behavior to layers, you can wrap them in a ScrollComponent, using ScrollComponent.wrap().

# Wrap the content layers 
scroll = ScrollComponent.wrap(content)

Content Inset

To add some extra spacing to your content, you can use the contentInset property. This is useful to place content within a scrollable area. Think of a header on top a list. You can’t scroll beyond the header, but you can scroll the feed.

# Create a ScrollComponent 
scroll = new ScrollComponent
    width: 120
    height: 120
    scrollHorizontal: false
# Define the contentInset 
scroll.contentInset =
    top: 40
    bottom: 40
    right: 0
    left: 0


The three fundamental scrolling events are: scrollStart, scroll (or ScrollMove) and scrollEnd. Within the Scroll event, the positions of the scrollable layer can be retrieved. For example, animations can be started based on the vertical scrolling distance with scroll.scrollY.

# Create a ScrollComponent 
scroll = new ScrollComponent
    scrollHorizontal: false
# Listen to the Scroll event 
scroll.onScroll ->
    if scroll.scrollY < -10
            scale: 1

Scroll Animation

Just like with draggable layers, there are two specific events that occur when momentum and bounce are enabled: ScrollAnimationDidStart and ScrollAnimationDidEnd. They occur after ScrollEnd.

# After Scroll, the ScrollAnimation starts 
scroll.onScrollAnimationDidStart ->
        width: 100
# After the scroll animation 
scroll.onScrollAnimationDidEnd ->
        width: 120


With the PageComponent, piecing together multiple static screens into a single, interactive prototype is a breeze. It handles all of the calculations, allowing you to focus on the experience.

The PageComponent allows you to easily swipe between layers, in any direction. It’s based on the ScrollComponent.

# Create a PageComponent 
page = new PageComponent
# Define first page layer 
layerA.parent = page.content
# Define second page layer place it to the right 
layerB.parent = page.content
layerB.x = 200

Adding Pages

New pages can be added by using page.addPage(). This takes a layer, and places it on the right side. Pages can also be added on the bottom.

# Create a PageComponent 
page = new PageComponent
# Add layerA to the right 
# Add layerB to the bottom 


To add pagination behavior to designed layers, you can wrap them in a PageComponent, using PageComponent.wrap().

# Wrap the content layer 
page = PageComponent.wrap(content)

Ordering and Sorting

Detecting a page-switch can be done with the change:currentPage event. This is really useful when designing things like page indicators.

# Listen to any page switch 
page.on "change:currentPage"->
        opacity: 0.2
        scale: 0.8
        opacity: 1
        scale: 1

You don’t always want to start at the first page. You can also automatically snap to a page layer, with or without an animation.

# Snap to the layer pageThree 
# Snap with a custom animation curve 
page.snapToPage(pageTwotruecurve: Spring)

Page Index

You can keep track of the index of your pages, measured either horizontally or vertically. The index is the page number, minus 1. This means the index will always start at 0 instead of 1. To highlight many of the mentioned properties and methods, have a look at this Page Indicator example.

page.on "change:currentPage"->
    for layer in indicators
            opacity: 0.5
    current = page.currentPage
    = page.horizontalPageIndex(current)
        opacity: 1


Sliders can be used to show progress, change the volume, adjust photos, define a price range and more. With the SliderComponent, you can build adaptable designs without having to start from scratch.

The SliderComponent consists of 3 layers: the slider itself, the fill and the knob. The slider is track of the slider. The knob is used to change the value of the slider. The fill represents the current value. You can change the appearance of these layers, just like any other layer.

The SliderComponent has a few unique properties:

  • min (minimum value)
  • max (maximum value)
  • value (starting value)
  • knobSize (width and height of the knob)
# Create Slider 
slider = new SliderComponent
    min: 0
    max: 100
    value: 50
    knobSize: 40
# Customize fill color 
slider.fill.backgroundColor = "#fff"

The slider itself is simply a Framer layer, meaning you can change all of its visual properties. Same thing goes for the fill and knob layers.

# Customize slider 
slider.backgroundColor = "#DDD"
# Customize fill 
slider.fill.backgroundColor = "#00AAFF"
# Customize knob 
slider.knob.shadowY = 2

Value Changes

With the onValueChange function, you can detect value changes, and retrieve the current value as it’s being changed.

# Create Slider 
slider = new SliderComponent
    min: 0
    max: 100
    value: 50
# Get the current value 
slider.onValueChange ->
    print slider.value

Start your free 14‑day trial.

Enter your email and we‘ll send you a download link for later.

The information in these videos may be outdated. To learn more about what changed, please visit our Help Center.