Overrides (pre X22)
This page is from before the launch of Framer X22 and explains Overrides using the older, now deprecated, animations. There’s an updated explanation of Overrides here.
Overrides (sometimes called code overrides) are a way to quickly make elements on your canvas interactive. With Overrides you can animate Frames and Components and also have them react to events like a tap, hover, drag, etc.
Applying an override
Open ‘Code’ in the Properties Panel to add an override to a (selected) frame.
In the Code tab you then pick which ‘File’ you want to use (there will be one with ‘Examples’), and also the exact ‘Override’ function inside that file.
Override files
From the same menu in the Code tab, you can open the existing ‘Example.tsx’ file in VS Code.
Selecting ‘New File…’ will create a new ‘App.tsx’ file which also contains an example override.
You can add more files if you want, and each file can contain many overrides. But you can only apply one override at a time to a frame.
What are you ‘overriding’?
With an override, you can dynamically change the properties of a Frame or Component. Any property that you can set in the Properties Panel can be changed (or sometimes animated) on the fly.
So you can change a frame’s size and position, but also its fill, border, shadow, etc.
This overriding happens between the Canvas and the Preview. Which means that the result of an override will only be visible in the Preview window.
As a simple example, here’s one that just changes the color of a frame:
export const ChangeColor: Override = () => {
return {
background: "red"
};
};


Whatever the frame’s Fill was on the Canvas (could be a color, gradient or image) will be overridden. The Frame will simply be red.
You’re overriding the Frame’s styling, its CSS properties, but you can also have it listen to events.
Events
By attaching an event to a frame, you can have it react to, for instance, a tap.
The Framer docs have an example of an override that just listens to an event. It doesn’t change anything on the frame itself, it just writes “Hello” to the Console.
import { Override } from "framer";
export function LogTap(): Override {
return {
onTap: () => {
console.log("Hello")
},
}
}
download this projectTo see the Console, select Inspect ⌘I from the hamburger menu on the Preview window. Or you can also right-click in the preview window and choose ‘Inspect Element.’
The Console is one of the tabs in the Web Inspector that will appear.
When you now tap the frame a “Hello” message will appear in the Console.

And now you also know that whenever you want to find out what’s happening inside an Override that you can log values to the Console.
To see a frame’s current properties (props
), for instance, you can do:
export const logProperties: Override = props => {
return {
onTap() {
console.log(props);
}
};
};
The example ‘Scale’ override
When selecting ‘New File…’ (from the ‘File’ menu) in the ‘Code’ tab, you’ll get a fresh App.tsx
file, with only one simple example override.
The override is Scale
,

Here’s the code:
import { Data, animate, Override, Animatable } from "framer"
const data = Data({ scale: Animatable(1) })
export const Scale: Override = () => {
return {
scale: data.scale,
onTap() {
data.scale.set(0.6)
animate.spring(data.scale, 1)
},
}
}
download this projectWhat is happening here? A lot.
This override…
- animates the
scale
property of the frame, - but not directly. It actually animates an
Animatable
value (also calledscale
) that is saved in an instance of Framer’sData
object. - The animation happens when the frame is tapped, it gets triggered by an
onTap()
event. - But because the animation is to the actual scale of the frame (
1
), the frame is first shrunk to 60% of its size (0.6
), so that it can grow again.
Anyway, to make everything a bit more understandable, we’ll take another look at the very simple override mentioned above, and then expand on it to create more complicated overrides.
The simplest possible Override
The ChangeColor
override below just changes the background
of the frame you attach it to. That’s all, no animation, there’s not even a tap needed to trigger it.


It’s the plainest possible override function.
import { Override } from "framer";
export const ChangeColor: Override = () => {
return {
background: "red"
};
};
download the example projectHere’s what’s happening.
- First, we import
Override
from the Framer Library. - Then we create an ES6 Arrow function (
=>
), - that we save in a
const
variable with the name ofChangeColor
, - while giving it the (TypeScript) type of
Override
. - Our function
return
s a JavaScript object which contains only one key-value pair: the key isbackground
with a value of"red"
. - Ah, and we make sure to
export
our function.
Okay, step by step, in more detail.
Importing another JavaScript file
import { Override } from "framer";
We import Override
from the Framer library so that we can create an override function. That’s also all we need from that library, for now.
Importing is like the script src
statement you would use to add a JavaScript library to your webpage, like, e.g., the jQuery library.
<script src="js/jquery-3.3.1.min.js"></script>
An ES6 Arrow function
In JavaScript, you can write functions, like, e.g., an add
function, this way:
function add(number1, number2) {
return number1 + number2
}
This is called a function declaration.
The add
function above takes two numbers and returns their sum. You would use it like this:
add(4,5);
You can try it in a Codepen here.
When you type the above line (at the bottom of that Codepen, in its Console), the function will return:
> 9
But can also write functions like this, in what they call a function expression:
add = function(number1, number2) {
return number1 + number2
}
Note how the name, add
, and the function
keyword switched place.
But we’ll use an Arrow (=>
) function, something new in ES6, which—with this same add
example—looks like this:
add = (number1, number2) => {
return number1 + number2
}
(ES6 refers to version 6 of the ECMA Script programming language. ECMA Script is the official name for JavaScript, and version 6 was finalized in June 2015. You might also see it being referred to as ‘ECMAScript 2015’)
And when the Arrow function doesn’t need any input values, like our ChangeColor
example, you can leave the parentheses empty.
TheAnswer = () => {
return 42;
}
(Try this example on Codepen.)
By the way, when you call the function, you do have to write the parentheses.
TheAnswer();
> 42
Back to our ChangeColor
function:
ChangeColor = () => {
return {
background: "red"
};
};
And what does our function do? It return
‘s the properties that should be changed on the frame.
Our function returns an object
The updated properties are returned as a JavaScript object.
{
background: "red"
}
This means that you can set several properties at once. You could, for instance, also change the rotation
of the frame:
ChangeColor = () => {
return {
background: "red",
rotation: 45
};
};
Our function is saved in a const
Our ChangeColor
variable, which contains the function, is a const
. This stands for ‘constant,’ a variable that cannot be changed afterward.
const ChangeColor = () => {
return {
background: "red"
};
};
The other option in ES6 is let
, and those variables can be changed.
let
is like the new version of what used to be var
in old school JavaScript, a variable that can be changed afterward.
It’s always better to use const
, though, because if you then (accidentally) try to use the same variable name for something else, VS Code will warn you.
Here I try to save a text string in our ChangeColor
variable:
ChangeColor = "A text string, for example.";
Which results in VS Code putting a squiggly red line under the variable to signal an error.

Hovering over the error brings up more information. Here: “Cannot assign to ‘ChangeColor’ because it is a constant.” (and above that, just to make it clear, the code I wrote to define ChangeColor
).
Our function has a TypeScript type of Override
In Framer Classic we used CoffeeScript, a language built on top of JavaScript that was easier to use and looked cleaner (no curly braces).
In Framer X we use TypeScript.
While CoffeeScript looked quite different from JavaScript, TypeScript is JavaScript. Well, with a few additions.
The main advantage of TypeScript is that you can give variables a predefined shape, a ’type’ (hence the name of the language).
You can define, for instance, that a variable should always contain a String, or a Number, or a Boolean.
Say you have a (let
) variable called totalPrice
, with a type of number
, that initially contains 0
:
let totalPrice: number = 0;
When you then give it another numeric value…
// updating the price
totalPrice = 100;
… everything will work fine.
But when you try to set it to a String…
totalPrice = "one hundred bucks";
… VS Code will complain.
You can also define which types of parameters a function will accept. Remember our simple addition function from higher up?
We can say that the number1
and number2
parameters it accepts should always be numbers.
const addNumbers = (number1: number, number2: number) => {
return number1 + number2
}
Back to our ChangeColor
function. We give our function the type of Override
.
const ChangeColor: Override = () => {
return {
background: "red"
};
};
This enables VS Code to check if our code is kosher because it knows what an Override
can and should contain. (That’s what we imported higher up: all the details about this Override type.)
Setting the type to Override
also makes the function discoverable by Framer. Only functions of this type will appear inside Framer’s Code tab. (And, by extension, only files that contain Override functions will show up in that Code tab.)
We ‘export’ the function
By writing export
before defining the function you make it so that Framer can import it and show it in its Code menu.
export const ChangeColor: Override = () => {
return {
background: "red"
};
};
So if you’re writing an override and it doesn’t show up in the Code menu, one of the following statements will be true:
- You forgot to type it as an Override (easy to solve)
- You forgot to export the function (piece of cake)
- Your function has an error
Errors are harder to fix, but that’s why we have VS Code. Any error in your code will be underlined with a scribbly red line. Hover over it for more information.
A bit more about const
To be honest, const
isn’t always a synonym for ‘immutable.’ It depends on what you’ve put inside that ‘const’ variable.
When it’s a String, Number, Boolean, or in our case, a function, then it’s true that the value can’t be ‘mutated.’
But when it contains an Array or Object, then the values inside that Array or Object can be changed.
const justAnObject = {
text: "I’m a text string"
};
justAnObject.text = "I’m now a different text string.";
More info: Use const
and make your JavaScript code better
More complicated Overrides
download the example projectSetting a property when tapped
Finally, some interaction!


import { Override, Animatable } from "framer";
const colorValue = Animatable("#66BB66");
export const ChangeColorOnTap: Override = () => {
return {
background: colorValue,
onTap() {
colorValue.set("red");
}
};
};
We animate values, not properties
Now we get to touch on something important.
In Framer, you don’t animate a property directly. You animate a value that you attached to a specific property.
You might say: “But we’re not even animating!” True, but we are changing the color. It starts off as green, #66BB66
, and then we change it to red
.
So we first create a variable to hold the color, colorValue
, that we set to the initial green color, "#66BB66"
:
const colorValue = Animatable("#66BB66");
Then, inside our return
statement, we attach colorValue
to the background
property:
background: colorValue,
Now, whenever we change colorValue
, it will, in turn, change the background
, because they’re bound together.
We also bind an onTap()
handler to the frame.
onTap() {
colorValue.set("red");
}
So that when it is tapped colorValue
will be set to "red"
.
Again, directly setting background
will not work, you have to change the value that you tied to the background
property.
Something like this (trying to set the property directly) does not work:
export const ChangeColorOnTap: Override = props => {
return {
onTap() {
props.background = "red";
}
};
};
The Animatable object
You noticed that we’re using this Animatable
object, which we’re now also importing from the Framer library.
import { Override, Animatable } from "framer";
That value you want to change (or animate) should be inside an Animatable
.
const colorValue = Animatable("#66BB66");
Framer will notify React of changes to an Animatable
object so that React knows when to update (re-render) the screen.
(By the way, the variable can be a const
because the object itself will not change, only the value we’re storing inside it.)
And to change the value, we use the Animatable’s set()
function:
colorValue.set("red");
Believe me, I tried, using a simple let
variable instead of an Animatable
, like this…
let colorValue = "#66BB66";
export const ChangeColorOnTap: Override = () => {
return {
background: colorValue,
onTap() {
colorValue = "red";
}
};
};
… will not work.
Animating a property when tapped


import { Override, Animatable, animate } from "framer";
const colorValue = Animatable("#66BB66");
export const AnimateColorOnTap: Override = () => {
return {
background: colorValue,
onTap() {
animate(colorValue, "red");
}
};
};
We need the animate
function, so we add it to our imports.
import { Override, Animatable, animate } from "framer";
But anyway, if you type animate
in your code without having it imported, VS Code will offer to add it to the import
statement. (A little light bulb will pop up when you click the error.)
Obviously, the value should be an Animatable
, so that we can animate it.
const colorValue = Animatable("#66BB66");
And again, we don’t animate the property itself (background
) but the value that we attached to it:
animate(colorValue, "red");
We animate colorValue
to a new value: "red"
.
We didn’t give animate
more details, so this animation will use the default settings: an ‘ease’ curve with a duration of one second.
Back to Framer’s example ‘Scale’ override
And now, we can take another look at that example that’s in every new overrides file:
import { Data, animate, Override, Animatable } from "framer"
const data = Data({ scale: Animatable(1) })
export const Scale: Override = () => {
return {
scale: data.scale,
onTap() {
data.scale.set(0.6)
animate.spring(data.scale, 1)
},
}
}
It’s not too difficult, is it?
The only extra thing happening here is that, when tapped, the scale
of the frame is made smaller (0.6
), just before it gets animated back to the original scale of 1
. (Otherwise it wouldn’t animate.)
And in this one, the Animatable
, named scale
, is placed inside Framer’s Data object.
Animating a property automatically


import { Override, Animatable, animate } from "framer";
const colorValue = Animatable("#66BB66");
export const AnimateColorInstantly: Override = () => {
animate(colorValue, "red");
return {
background: colorValue
};
};
You can have an animation start right away, by kicking it off before even returning the properties to the frame.
animate(colorValue, "red");
return {
background: colorValue
};
So here we start with animating colorValue
, and only then we say: “By the way, this should be the value of the background. Apply it, because it’s already changing!”
(The other way round will not work, because a return
is always the end of a function.)
With this technique, the frame will animate the moment it appears. (So you can use it in click-through prototypes.)
Starting from the current value of a property
By the way, we actually don’t have to set the start color, we could read the frame’s current color.
All the frame’s properties are inside a props
object that we can pass in.
Look, for example, at the Fade
override in Framer’s Examples.tsx
:
const data = Data({
opacity: Animatable(1)
});
export const Fade: Override = props => {
data.opacity.set(props.opacity)
return {
opacity: data.opacity,
onTap() {
animate.linear(data.opacity, 0)
},
}
}
The opacity
animatable is set to a start value of 1
.
But, just to be sure, the override also gets the current opacity from the frame’s props
.
Often an override function doesn’t need any of the frame’s existing properties so you can leave its parameters empty: ( )
.
export const Fade: Override = () => {
...
But when you add the props object, like this:
export const Fade: Override = props => {
...
You can get the current value of any of the frame’s properties.
This way we can set data.opacity
to the frame’s current opacity, props.opacity
, before we do anything else.
data.opacity.set(props.opacity)
6 comments on “Overrides (pre X22)”
Comments are closed.
Your way of explaining is amazing. Thanks for this.
Thank you!
hello, when I used:
opacity: Animatable(1)
and
data.opacity.set(props.opacity)
but it is alert all the time, how can I deal with it?
thanks.
These APIs are probably not fully supported in the current version of the Framer library.
Try to change the ‘Framer Library Version’ (see ‘File’ menu) to an older one.
Thanks for replying.
So, how can I get the current value of a property in current version ?
Good question, because it seems that it’s not possible anymore.
I tried with
opacity
,left
androtate
:The values will be set to the current
props
(so the initial0
values will be overwritten)… but then nothing happens when theonTap()
is triggered.When you delete the lines that get the current props:
… then the animation does work. But then, obviously, the Frame’s opacity, left and rotate are set to zero when it appears.
BTW, I also tried with Koen Bok’s useStore hook, but that didn’t make a difference.
Maybe somebody on the Slack or Spectrum knows how to do it. I would ask there.