How to Use TextMobject and Manage Fonts for Text Rendering in Manim

Manim renders vector-based text using the Pango library via manimpango, where the Text class (historically referred to as TextMobject) inherits from MarkupText in manimlib/mobject/svg/text_mobject.py and resolves fonts through a three-tier hierarchy of global configuration, scene-level overrides, and per-instance constructor arguments.

The 3b1b/manim repository (Grant Sanderson’s original animation engine) handles text rendering through a sophisticated SVG-based pipeline. Whether you are displaying mathematical explanations or UI labels, understanding how to use the Text class and manage font selection is essential for crisp, scalable typography in your animations.

Understanding the Text Class Hierarchy

Manim’s text system is built on a chain of inheritance that converts strings into SVG paths. The core implementation lives in manimlib/mobject/svg/text_mobject.py.

Text, MarkupText, and StringMobject

The hierarchy flows from SVGMobject down to concrete text classes:

  1. StringMobject – Base class for string-based SVG mobjects.
  2. MarkupText – Inherits from StringMobject. It builds an SVG by converting a Pango markup string via markup_to_svg (see lines 53‑62).
  3. Text – Inherits from MarkupText. It overrides the markup parsing to treat input as plain text, escaping only the markup characters (see the overridden static methods at lines 21‑35).

This architecture means Text objects are ultimately collections of VMobject paths derived from font glyphs, allowing for standard Manim transforms like Write, FadeIn, and complex color mapping.

Font Resolution and Configuration

Font selection in Manim operates through a cascading priority system defined in the __init__ method of MarkupText around lines 68‑78.

Global Defaults in default_config.yml

The base font configuration resides in manimlib/default_config.yml at lines 88‑90:

text:
  font: "Consolas"
  alignment: "LEFT"

By default, all Text objects render using Consolas unless overridden.

Per-Scene and Instance Overrides

You can override fonts at two additional levels:

  1. Scene-level – Modify manim_config.text.font at runtime or via a custom --config_file:
from manimlib import *

config.text.font = "Times New Roman"

class Example(Scene):
    def construct(self):
        # This uses Times New Roman by default

        t = Text("Scene Default Font")
        self.add(t)
  1. Instance-level – Pass font="Font Name" directly to the constructor. This takes highest priority (see line 75 where self.font = font or text_config.font):
Text("Override Example", font="Arial")

Registering Custom Font Files

Manim does not ship with every system font. To use a custom TTF or OTF file that is not installed system-wide, use the register_font context manager defined at lines 69‑99 in the same file.

This context manager temporarily adds the font file to Pango’s search path:

from manimlib import *

class CustomFontScene(Scene):
    def construct(self):
        with register_font("fonts/UbuntuMono-R.ttf"):
            # "Ubuntu Mono" must match the font family name inside the TTF

            text = Text(
                "Custom Font Rendering",
                font="Ubuntu Mono",
                t2f={"Custom": "Comic Sans MS"}  # Mix fonts within text

            )
        self.play(Write(text))

Critical note: The string passed to font= must match the font family name embedded in the TTF metadata, not the filename.

Text Scaling and Alignment

Scaling Calibration

The size of a Text object is calibrated so that a reference glyph "0" has a height of 1 Manim unit. This scaling factor is calculated by get_text_mob_scale_factor at lines 103‑113.

When you call .scale(2), the text doubles in size relative to this calibrated baseline.

Alignment Options

Horizontal alignment defaults to the config value (text.alignment) but can be overridden per object via the alignment parameter:

  • "LEFT" (default)
  • "CENTER"
  • "RIGHT"
Text("Right aligned", alignment="RIGHT").to_corner(DR)

For multiline text, control vertical spacing with lsh (line spacing height):

Text("Line 1\nLine 2", lsh=1.5)  # 1.5x default spacing

Styling Shortcuts for Text

The Text class supports dictionary-based styling that maps text selectors to visual properties. These are applied after SVG generation (see get_configured_items at lines 98‑116):

  • t2c – Text to color
  • t2f – Text to font
  • t2g – Text to gradient
  • t2s – Text to slant (ITALIC, NORMAL, OBLIQUE)
  • t2w – Text to weight (BOLD, THIN, etc.)
Text(
    "Colorful Bold Manim",
    t2c={"Colorful": BLUE, "Manim": RED},
    t2w={"Bold": BOLD},
    t2f={"Manim": "Times New Roman"}
)

Summary

  • Inheritance chain: TextMarkupTextStringMobject in manimlib/mobject/svg/text_mobject.py, converting strings to SVG paths via Pango.
  • Font resolution: Three-tier priority system—global config (default_config.yml), scene override (config.text.font), and instance argument (font="Name").
  • Custom fonts: Use the register_font context manager to temporarily load TTF/OTF files not installed system-wide.
  • Scaling: Reference glyph "0" equals 1 Manim unit; use alignment and lsh for positioning and line spacing.
  • Styling: Apply t2c, t2f, t2g, t2s, and t2w dictionaries for per-word formatting.

Frequently Asked Questions

What is the difference between Text and TextMobject in Manim?

In the 3b1b/manim repository (ManimGL), the modern class is Text, which inherits from MarkupText. Earlier versions and the community edition (ManimCE) historically used TextMobject for LaTeX-based text and Text for Pango-based rendering. In current ManimGL, Text is the standard class for plain text rendering using system fonts via Pango.

How do I use a custom TTF font that is not installed on my system?

Wrap your Text instantiation in the register_font context manager imported from manimlib.mobject.svg.text_mobject. Pass the path to your .ttf or .otf file as the argument. Inside the context block, reference the font by its family name (as defined in the font metadata) in the font parameter of Text.

Why is my text appearing as squares or not rendering correctly?

Squares typically indicate missing glyph coverage or font not found. Verify that the font name passed to font= exactly matches the family name in the font file metadata (not the filename). If using a custom font file, ensure you are using register_font. Additionally, check that manimpango and Pango are properly installed in your environment, as these are required for SVG text generation.

How do I change the default font for all text in a scene?

Modify the config.text.font attribute before constructing your Text objects. You can set this in your scene’s __init__ or at the module level: config.text.font = "Arial". Alternatively, create a custom default_config.yml and pass it via the --config_file CLI argument to override the global defaults defined in manimlib/default_config.yml.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →