Can Typst produce animated PDFs?

I recently discovered that you can embed animations directly in PDF files. For example, Adobe InDesign supports QuickTime video integration into PDFs. On the FOSS/LaTeX side, two main approaches exist:

  • animate package
    • Supply a sequence of frames (e.g. TikZ-generated images)
    • Works in Adobe Acrobat, Firefox’s PDF.js, Okular (though playback can be less smooth), PDF‑XChange, Foxit Reader, etc.
  • TikZ Animations Library (experimental)
    • Define keyframes and let TikZ interpolate between them

I’ve successfully used the animate package with TikZ to create simple frame‑by‑frame animations, and it “just works” in the readers I mentioned. I’m happy to share my LaTeX examples (both source and resulting PDF) if that helps frame the discussion.

Why Animated PDFs Matter

Although PDFs were originally designed for static, print‑oriented documents, today they’ve become the de facto standard for distributing digital content. Especially in academia, embedded animations can significantly enhance:

  • Teaching materials: Step‑by‑step visualizations of algorithms, physical phenomena, or data transformations.
  • Scientific communications: Previewing time‑series data, simulations, or experimental setups without leaving the PDF.
  • General documentation: Animated flowcharts, UI walkthroughs, or process demos.

For more on the pedagogical power of animated PDFs, see Joe Reddington’s blog post:

“…you can communicate complex ideas far more clearly with motion than with static diagrams alone.”
Why don’t my pdfs have animated gifs? | Joe Reddington

My Questions for the Typst Community

  1. Is there a way to generate animated (or video‑embedded) PDFs directly from Typst?
  2. If not today, is the hurdle in the Typst core (e.g. PDF backend limitations), or simply a lack of extensions/libraries?
  3. Are there any workarounds, perhaps via external tools or post‑processing, that play nicely with a Typst‑first workflow?
11 Likes

Since this post hasn’t gotten any answers, I wanted to ping this again, as I am also curious about animation support in Typst.

1 Like

Currently, Typst doesn’t support animated PDF’s or video embeds. Packages can’t write raw PDF data directly, support from Typst for the features is needed.

There is an open feature request for video support.

“Animated PDFs” in the sense of step‑by‑step visualizations are possible with some presentation slide packages e.g. , touying or polylux. There, for each “animation step” an extra PDF page gets generated.

However, support for true animations, such as those created with the LaTeX animate package, is apparently quite problematic. @reknih recently wrote on Discord:

The rabbit hole I just went down is to determine how animated PDFs work (and hence, whether we want/need to support that or whether something like frame is okay). Needless to say that it is completely cursed and I don’t feel we need to support it, ever.
(They use widget annotations with content streams that represent the current frame. They are all stacked on top of one another and one of them has a JavaScript Action that gets triggered when the page is opened and continually cycles the annotations’ visibility using setTimeout)
My hunch was that they’d use Optional Content Groups but it’s apparently more cursed than that

2 Likes

I haven’t seen a PDF with an animation in it before (perhaps I’m missing out) and I wonder whether it would work across a range of different readers/platforms, but I did recently use Typst to create an animated GIF, and I’ll include a few notes here for the benefit of anyone else who might be interested.

  1. Make a typst file that has a frame on each page.
  2. Have typst compile each page to a separate png file.
  3. Combine the png files using another tool like ImageMagick.

For details of how I created this animated gif, see below (using a Macbook, and I imagine similar tools would work on Linux. I’m not sure how easy it would be in Windows.)

animation

demo.typ:

#set page(height: 9.1cm, width: 15.3cm, margin: 0cm)

#let show-frame(frame_number) = {
  rect(fill: blue, 
       width: {frame_number} * 0.5%, 
       height: {frame_number} * 0.5%)
}

#for i in range(1, 201) {
  show-frame(i)
  pagebreak(weak: true)
}

make_animation.sh:

#! /bin/zsh -v

mkdir frames
rm frames/*.png
typst compile -f png demo.typ "frames/frame-{0p}.png"
magick -delay 5 -loop 0 frames/frame-*.png animation.gif  

# (change loop 0 to loop 1 so it just animates once instead)
1 Like

that’s one of the cases where I think page(...) makes more sense than pagebreak():

#for i in range(1, 201) {
  page(show-frame(i))
}

Doesn’t make a difference in result, but it just seems natural in this context

4 Likes

Wow! I have been using Typst for the past 18 months and I didn’t know that you could just use page as a function like that.

Moreover, you don’t need the curly braces around the variable number as you are already in code mode and don’t compute any complex code inside that block.

1 Like