Expressions
An expression replaces a property’s sampled value with a computed one, evaluated every frame. Use it when a relationship is easier to state than to keyframe: “always half the parent’s rotation”, “wobble around this value”, “follow that layer with a delay”.
The editor
The expression editor is in the Graph panel (Window ▸ Panels ▸ Graph Panel): pick a property of the selected layer and write its expression there.
- Monospaced, with autocomplete at the caret — ranked, member-aware, and on Ctrl + Space.
- A pick-whip: drag from the editor’s header onto a property row or a layer to insert a reference to it.
- Inline plain-language errors rather than a stack trace.
- A live value that updates as you scrub the playhead — so you can see what the expression is producing before you commit to it.
- AI assist produces an editable expression, never a locked black box. You can read it, change it, and delete the parts you do not want.
Expression controls
Controls are named inputs that live on a layer and can be referenced from any expression. They turn an expression into something with a UI.
| Control | Type |
|---|---|
| Slider | Number |
| Angle | Degrees |
| Point | 2D vector |
| Colour | RGBA |
| Checkbox | Boolean |
| Dropdown | Enumerated choice |
| Layer | A reference to another layer |
Add Expression Control is in the toolbar’s Animate menu, with one entry per kind. It creates a named control you then reference:
ctrl('Wobble Amount')Because the control is itself a property, it can be keyframed — which is how you animate the parameters of an expression rather than the value directly.
The language
A real expression language with vector support, evaluated per frame by the engine’s own interpreter. Expressions can read other properties, other layers, the current time and the composition’s parameters.
It is written to feel like After Effects’ expressions, and the time-sampling
set the common idioms are built on is there: valueAtTime, velocityAtTime,
key(n), nearestKey(), numKeys, loopIn / loopOut, posterizeTime,
wiggle, timeToFrames / framesToTime, alongside thisLayer,
thisProperty and thisComp. A bounce or an inertial follow written for After
Effects usually ports as it is. It is not the whole of After Effects’ JavaScript
engine: an expression that leans on general-purpose JavaScript may need
rewriting.
A text layer’s Source Text can take an expression too (Layer → Text → Source Text Expression…), so what a layer says can be computed.
Coordinate spaces
Four functions convert a point between a layer’s own space, the composition and the world — which is what you need whenever one layer must follow a point on another layer that is itself parented, rotated or scaled:
toComp(point) fromComp(point)
toWorld(point) fromWorld(point)Measuring a layer
sourceRectAtTime() gives a layer’s own bounding box at a time. It is how you
write motion that adapts to content instead of to numbers you typed — a
background plate that fits its text layer, a underline that matches a heading
whose words change.
Reading keyframes and markers
Expressions can read the keyframes on a property, not just the sampled value
— their times and their values — and reach both composition and layer markers
through marker.*. Driving motion from markers you place on the ruler is
usually more legible than hard-coded times, because the timing stays visible in
the timeline.
Randomness and vector maths
Seeded randomness and the usual vector helpers. Seeded matters: an expression whose randomness changed per render would make two exports of one project differ, which the render model does not allow.
Expressions are evaluated inside the native engine by its own interpreter.
They are never handed to a JavaScript runtime to eval, in the editor or in a
headless render — which is also why an expression gives the same value in the
viewport, in an export and from the command line.
Expressions and keyframes together
An expression and a track are not mutually exclusive. The common pattern is:
- Keyframe the base motion.
- Add an expression that reads the sampled value and modifies it — adding a wobble, clamping it, offsetting it by another layer’s value.
That keeps the timing editable in the timeline while the expression handles the relationship.
Turning one off, and baking one down
Two things you can do to an expression short of deleting it:
| Action | What happens |
|---|---|
| Disable the expression | It stops driving the property but stays on it. The property falls back to its keyframes or its static value |
| Animation → Convert Expression to Keyframes | Samples the expression across the range and writes ordinary keyframes, then the expression’s job is done |
Disabling is the one to reach for while debugging: it answers “is the expression causing this?” without you losing the expression to find out.
Converting is how you hand a project to someone else, or how you take an expression as a starting point — generate the motion, bake it, then edit the keys by hand. It is also the escape hatch when an expression is doing something almost right.
When not to use one
- If a preset does it. Wiggle, pulse, shake and sway all exist as presets that write ordinary keyframes, which are easier to retime later.
- If you will need to hand the project to someone else. Keyframes are legible to anyone; an expression is legible to whoever wrote it.
- If the relationship is one-off. Two keyframes beat a line of code for a single move.
Related
- Keyframes
- Animation presets
- The AI assistant —
set_expressionis one of its tools