remotion lower-thirds text-animation react motion-graphics

Lower Thirds and Text Animations in Remotion — Complete Guide

Lower Thirds and Text Animations in Remotion — Complete Guide

Lower thirds, kinetic text reveals, and typewriter effects are among the most requested motion graphics elements in video production. In traditional NLEs you build these by hand on a timeline. In Remotion, you write them once as React components and reuse them infinitely — passing different names, titles, and colours as props.

This guide covers three techniques in depth: animated lower thirds, text reveal animations, and typewriter effects. Each section includes working code and notes on where a pre-built template saves you significant time.


What Is a Lower Third?

A lower third is the text overlay that appears in the lower portion of a video frame — typically a speaker’s name and title. In broadcast television, lower thirds are produced by dedicated graphics systems. In Remotion, a lower third is just a React component that reads useCurrentFrame().


Building an Animated Lower Third

A well-crafted lower third typically has three phases:

  1. In — the element slides or fades into view
  2. Hold — the text is fully visible for the speaker to read
  3. Out — the element exits before the next cut

Here is a minimal implementation using interpolate and spring:

import {
  interpolate,
  spring,
  useCurrentFrame,
  useVideoConfig,
} from "remotion";

interface LowerThirdProps {
  name: string;
  title: string;
  accentColor?: string;
}

export const LowerThird: React.FC<LowerThirdProps> = ({
  name,
  title,
  accentColor = "#e63946",
}) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();

  // Slide up on enter
  const translateY = spring({
    fps,
    frame,
    config: { damping: 14, stiffness: 120 },
    from: 40,
    to: 0,
  });

  // Fade in
  const opacity = interpolate(frame, [0, 12], [0, 1], {
    extrapolateRight: "clamp",
  });

  // Bar width reveal
  const barWidth = interpolate(frame, [0, 20], [0, 6], {
    extrapolateRight: "clamp",
  });

  return (
    <div
      style={{
        position: "absolute",
        bottom: 120,
        left: 80,
        transform: `translateY(${translateY}px)`,
        opacity,
        display: "flex",
        alignItems: "center",
        gap: 16,
        fontFamily: "-apple-system, Segoe UI, Roboto, sans-serif",
      }}
    >
      {/* Colour accent bar */}
      <div
        style={{
          width: barWidth,
          height: 56,
          background: accentColor,
          borderRadius: 2,
        }}
      />
      <div>
        <div
          style={{
            color: "#ffffff",
            fontSize: 28,
            fontWeight: 700,
            letterSpacing: 0.5,
          }}
        >
          {name}
        </div>
        <div
          style={{
            color: "rgba(255,255,255,0.75)",
            fontSize: 18,
            fontWeight: 400,
          }}
        >
          {title}
        </div>
      </div>
    </div>
  );
};

Composing the Lower Third into a Scene

Wrap the component in a <Sequence> to control when it appears:

import { Sequence } from "remotion";
import { LowerThird } from "./LowerThird";

export const InterviewScene: React.FC = () => (
  <>
    {/* Lower third: visible from frame 30 to frame 150 */}
    <Sequence from={30} durationInFrames={120}>
      <LowerThird name="Hiromi Ishino" title="CEO, Trimora Inc." />
    </Sequence>
  </>
);

Text Reveal Animations

Text reveals animate individual words or characters into view. Two popular styles are the wipe reveal (text slides in from behind a mask) and the fade-up reveal (each word staggers upward).

Word-by-Word Fade-Up

import { interpolate, useCurrentFrame } from "remotion";

interface WordRevealProps {
  text: string;
  startFrame?: number;
  staggerFrames?: number;
}

export const WordReveal: React.FC<WordRevealProps> = ({
  text,
  startFrame = 0,
  staggerFrames = 6,
}) => {
  const frame = useCurrentFrame();
  const words = text.split(" ");

  return (
    <div
      style={{
        display: "flex",
        flexWrap: "wrap",
        gap: 12,
        fontFamily: "-apple-system, Segoe UI, Roboto, sans-serif",
        fontSize: 64,
        fontWeight: 700,
        color: "#fff",
      }}
    >
      {words.map((word, i) => {
        const wordFrame = startFrame + i * staggerFrames;
        const progress = interpolate(frame, [wordFrame, wordFrame + 15], [0, 1], {
          extrapolateLeft: "clamp",
          extrapolateRight: "clamp",
        });
        return (
          <span
            key={i}
            style={{
              opacity: progress,
              transform: `translateY(${(1 - progress) * 24}px)`,
              display: "inline-block",
            }}
          >
            {word}
          </span>
        );
      })}
    </div>
  );
};

Typewriter Effect

The typewriter effect reveals characters one by one, mimicking the feel of live typing. It works by slicing the string at a frame-derived index:

import { interpolate, useCurrentFrame } from "remotion";

interface TypewriterProps {
  text: string;
  durationInFrames?: number;
  cursorVisible?: boolean;
}

export const Typewriter: React.FC<TypewriterProps> = ({
  text,
  durationInFrames = 90,
  cursorVisible = true,
}) => {
  const frame = useCurrentFrame();

  const characterIndex = Math.floor(
    interpolate(frame, [0, durationInFrames], [0, text.length], {
      extrapolateRight: "clamp",
    })
  );

  const showCursor = cursorVisible && frame % 30 < 15;

  return (
    <div
      style={{
        fontFamily: '"Courier New", Courier, monospace',
        fontSize: 48,
        color: "#e2e8f0",
        whiteSpace: "pre",
      }}
    >
      {text.slice(0, characterIndex)}
      {showCursor && <span style={{ opacity: 1 }}>|</span>}
    </div>
  );
};

Performance Notes

Text animations are cheap to render because they are pure CSS transforms — no image decoding, no video decode. Even a complex layered lower third with spring animations adds minimal overhead to your render pipeline.


When to Use Pre-Built Templates

The code above gives you the building blocks. But in a real production scenario — where you have a dozen lower third variants, different brand colours, multiple aspect ratios, and a deadline — building from scratch multiplies quickly.

RenderComp includes a curated set of lower third and text animation templates among its 1,400+ Remotion components. Each one ships with editable props for colour, font size, timing, and position. For agencies and freelancers who regularly produce interview-style or branded content, starting from a battle-tested template and adapting it is significantly faster than writing spring physics from scratch for every project.


FAQ

Q: How do I make a lower third disappear before the video ends? A: Set durationInFrames on the wrapping <Sequence>. When the sequence ends, the component unmounts. You can also add a fade-out by reading useCurrentFrame() relative to the end of the sequence.

Q: Can I animate text along a path in Remotion? A: Yes. Use an SVG <textPath> element inside your React component. Drive the startOffset attribute with interpolate() to animate text along a curve.

Q: How do I match the font in my lower third to my brand? A: In Remotion you can load a local font file using @remotion/fonts or by importing it as a static asset. Avoid loading fonts from external CDNs — load them locally for reproducibility and offline rendering.

Q: What is the best way to animate Chinese, Japanese, or Korean text? A: Use a system font stack that includes CJK fonts (e.g., "Yu Gothic", "Hiragino Kaku Gothic ProN", "Noto Sans JP", sans-serif). Character-level animations work fine — split the string by character rather than by space since CJK scripts do not use spaces as word boundaries.

Q: Can I use variable fonts in Remotion for animated font weight? A: Yes. Pass a CSS font-variation-settings style prop and drive the weight axis value with interpolate().

Q: How do I export just the lower third with a transparent background? A: Use npx remotion render --codec=prores-4444 or --codec=vp8/vp9 with --transparent. This outputs an alpha-channel video you can composite in any NLE.

Q: Is there a way to preview the lower third against a real video background? A: Yes. Use the <Video> or <OffthreadVideo> component in Remotion to place a background clip in your composition, then layer the lower third on top. Preview in Remotion Studio.


Conclusion

Lower thirds and text animations in Remotion follow the same pattern as every other motion graphics element: frame number in, visual state out. Once you internalise interpolate and spring, you can replicate virtually any text animation you see in professional broadcast productions — and export it as reusable, version-controlled React code.

For teams that need to ship these quickly at scale, browsing a template library like RenderComp first is worth the time investment.

Ready to ship

Get 1,400+ Remotion Templates

Lifetime license. TypeScript-first. Ship polished video in minutes, not days.

Get RenderComp →