Text¶
Text¶
Text is a multi-span text node. Create it, then call .span(text) to add lines of text.
Each span can have its own color, font size, weight, and style.
Output image
Multiple spans stack vertically as separate lines:
with Scene():
t = Text()
t.span("First line").font_size(22).color("darkslateblue")
t.span("Second line").font_size(22).color("steelblue")
t.span("Third line").font_size(22).color("cornflowerblue")
Output image
Inline groups¶
Use .group() on a Text or TextGroup to place spans side-by-side on the same line.
with Scene():
t = Text()
g = t.group()
g.span("Bold").bold().font_size(26).color("darkred")
g.span(" normal ").font_size(26).color("gray")
g.span("Italic").italic(True).font_size(26).color("darkblue")
Output image
Font styling¶
All text nodes share the same set of style methods:
| Method | Description |
|---|---|
.font_size(px) |
Font size in pixels |
.font(name) |
Font family name, e.g. "serif", "monospace", or font name |
.bold() |
Shortcut for .font_weight(800) |
.font_weight(w) |
Weight value (100–900) |
.italic(True) |
Enable italic |
.color(c) |
Text fill color |
with Scene():
t = Text()
t.span("Small").font_size(14).color("gray")
t.span("Medium").font_size(22).color("steelblue")
t.span("Large").font_size(36).bold().color("darkslateblue")
Output image
To use your own font files, add a font_directories key to fairyflow.toml. FairyFlow scans each listed directory recursively and loads all fonts it finds (.ttf, .otf, .ttc, .otc, .woff, .woff2). Paths are relative to the project root.
After adding fonts, refer to them by family name in .font():
Font aliases¶
The [font-aliases] table in fairyflow.toml maps CSS generic family names to specific fonts. This lets you pin which font backs "sans-serif", "monospace", etc., so renders are consistent across machines regardless of system fonts.
Any CSS generic family name is accepted as a key: serif, sans-serif, monospace, cursive, fantasy, system-ui, ui-serif, ui-sans-serif, ui-monospace, ui-rounded, emoji, math, fangsong. Generic families not listed here keep their system defaults.
The target font must be loaded — either from font_directories or from system fonts — before the alias takes effect.
Positioning¶
Text supports .xy(), .align_x(), .align_y(), and .move() for placement — see Positioning for details.
stext¶
stext is a helper that builds a Text node from a string with optional inline markup.
Tags can carry style attributes that are applied immediately, and the tag name is also
preserved as a .name() on the span or group so you can look it up later.
Inline color and style¶
Use a color attribute on any named tag to set the text color:
with Scene():
stext('<info color="green">INFO</info> server started').font_size(22).font("monospace")
Output image
with Scene():
stext('<span color="#e06c75" bold>ERROR</span> something went wrong').font_size(22).font("monospace")
Output image
Supported attributes¶
| Attribute | Effect |
|---|---|
color='...' |
Text fill color (any CSS color) |
font-size='N' |
Font size in pixels (also accepted: text-size) |
font='...' |
Font family |
font-weight='N' |
Numeric weight (100–900) |
bold |
Shorthand for font-weight='800' |
italic |
Enable italic |
Multiple attributes on one tag are all applied:
Named spans¶
The tag name is still recorded via .name(), so you can look the span up and restyle it later:
t = stext("<title>FairyFlow\n<subtitle>Animation for Python")
t.find_node(name="title").font_size(32).bold().color("steelblue")
t.find_node(name="subtitle").font_size(18).color("gray")
Literal < characters¶
A < that has no matching > is treated as literal text, so you can safely pass
arbitrary content (terminal output, ASCII art, file paths) without escaping:
stext("a < b") # → "a < b"
stext("path/to/<file>") # → tag named "file" — wrap in a real tag name only when intended
By default stext uses <tag>...</tag> syntax. Pass delimiters="[]" to use [tag]...[/tag] instead.
Syntax highlighting¶
Enable source-code syntax highlighting on a Text node with .sh(language).
Output image
An optional .sh(language, theme=...) argument selects the color theme.
Preinstalled themes:
- "InspiredGitHub" (default)
- "base16-ocean.dark"
- "base16-eighties.dark"
- "base16-mocha.dark"
- "base16-ocean.light"
- "Solarized (dark)"
- "Solarized (light)"
with Scene(color="#2b303b"):
stext(
"""
x = "world"
print(f"Hello {x}!")
"""
).sh("Python", theme="base16-ocean.dark").font("monospace")
Output image