Skip to main content

Text

MotionScript provides two text nodes: Text for single-style strings and RichText for multi-style spans. Both support fills, strokes, shadows, and all standard node animations.

Text

Text renders a string with a single consistent style.

import { Scene, Text, createRef, wait } from '@motion-script/core';

export class MyScene extends Scene {
*build() {
this.add(
<Text
text="Hello, MotionScript!"
fontSize={48}
fontFamily="Inter"
fontWeight={700}
fill="white"
/>
);

yield* wait(2);
}
}

Props

PropTypeDefaultDescription
textstring''Text content
fontSizenumber | 'autofit'16Font size in pixels, or 'autofit' to scale to bounds
fontFamilystring'Roboto'Font family name
fontWeightnumber400Weight: 100 (thin) to 900 (black)
letterSpacingnumber0Extra spacing between characters
lineHeightnumber1.2Line height multiplier
alignnumber0Alignment: -1 left, 0 center, 1 right
wrapbooleanfalseEnable text wrapping
minFontSizenumber12Minimum font size when fontSize: 'autofit'
Size defaults

When fontSize is 'autofit' or wrap is true, the node defaults to width: 'fill' and height: 'fill' so it expands to fit its container.

Alignment

align is a number, not a string:

<Text text="Left" align={-1} fontSize={32} fill="white" />
<Text text="Center" align={0} fontSize={32} fill="white" />
<Text text="Right" align={1} fontSize={32} fill="white" />

Autofit

Set fontSize="autofit" and give the node a fixed size — the text will scale down to fit, never going below minFontSize:

<Rect width={400} height={200} borderRadius={12} fill="#1e293b" padding={20}>
<Text
text="This text fits itself!"
fontSize="autofit"
minFontSize={12}
fill="white"
wrap={true}
/>
</Rect>

Word wrap

Enable wrap and give the node an explicit width (or put it inside a layout that provides one):

<Text
text="MotionScript lets you write animations as TypeScript generator functions."
fontSize={24}
wrap={true}
width={500}
lineHeight={1.5}
fill="#cbd5e1"
/>

Animating text

text animates by character interpolation — letters appear or disappear smoothly:

import { Scene, Text, createRef, parallel, easeOut } from '@motion-script/core';

export class MyScene extends Scene {
*build() {
const title = createRef<Text>();

this.add(
<Text ref={title} text="Motion Script" fontSize={80} fontWeight={800} fill="white" opacity={0} />
);

yield* parallel(
title().to({ opacity: 1 }, 0.8, easeOut),
title().to({ y: 20 }, 0.8, easeOut),
);

yield* title().to({ opacity: 0 }, 0.4);
}
}

Append and prepend

Use append and prepend to animate text growing character by character:

const label = createRef<Text>();
this.add(<Text ref={label} text="Hello" fontSize={48} fill="white" />);

yield* label().append(' world!', 1.5);
yield* label().prepend('>>> ', 1);

Gradient fill on text

Apply any fill type — including gradients — to a Text node:

<Text
text="Gradient"
fontSize={96}
fontWeight={900}
fill={{ type: 'linear-gradient', colors: ['#4f80ff', '#e84393'], stops: [0, 1] }}
/>

RichText

RichText renders mixed-style text using a tree of spans. Each span can override the font family, size, weight, letter spacing, fill, and stroke of its parent.

import { Scene, RichText, wait } from '@motion-script/core';

export class MyScene extends Scene {
*build() {
this.add(
<RichText
fontSize={40}
fill="white"
spans={[
{ text: 'Hello ' },
{ text: 'world', fill: 'royalblue', fontWeight: 700 },
{ text: '!', fill: '#e84393', fontSize: 60 },
]}
/>
);

yield* wait(2);
}
}

Props

PropTypeDefaultDescription
spansTextSpan | TextSpan[][]Span tree
fontSizenumber16Default font size (inherited by spans)
fontFamilystring'Roboto'Default font family
fontWeightnumber400Default font weight
letterSpacingnumber0Default letter spacing
lineHeightnumber1.2Line height multiplier
alignnumber0Horizontal alignment (-1, 0, 1)

TextSpan interface

interface TextSpan {
text?: string; // Text content of this span
fontFamily?: string; // Override font family
fontSize?: number; // Override font size
fontWeight?: number; // Override font weight
letterSpacing?: number; // Override letter spacing
fill?: FillProp | FillProp[]; // Override fill
stroke?: StrokeProp | StrokeProp[]; // Override stroke
children?: TextSpan[]; // Nested spans (inherit this span's styles)
}

Children inherit all style values from their parent span, overriding only what they explicitly set.

Nested spans

<RichText
fontSize={32}
fill="white"
spans={[
{
text: 'The ',
},
{
// This span sets a color; its children inherit it
fill: 'royalblue',
children: [
{ text: 'quick ' },
{ text: 'brown', fontWeight: 900 }, // bold + royalblue
{ text: ' fox' },
],
},
{ text: ' jumps.' },
]}
/>

Multi-line rich text

Use \n inside a span's text to break lines:

<RichText
fontSize={28}
fill="white"
spans={[
{ text: 'Line one\n' },
{ text: 'Line two', fill: '#94a3b8' },
]}
/>