Skip to content

Reference

The whole public surface of Animo. The guide explains these names, and this page states their signatures.

#import "@preview/animo:0.2.0": *

A star import brings in the body-level names and the anim module as a name. The timeline vocabulary is imported inside an animation block with import anim: *, where shadowing typst's own hide, move and scale is harmless.

Name Kind Written in
animo document show rule the top of the file
slide element the document
tag element a slide body
region element a slide body
per-subslide element a body or a layer
slide-number context function anywhere
slide-count context function anywhere
output-type context function anywhere
animo-logo content anywhere
made-with-animo content anywhere
anim.init initial state an animation block
anim.sub subslide an animation block
anim.reveal continuous a sub call
anim.hide continuous a sub call
anim.move continuous a sub call
anim.scale continuous a sub call
anim.pan continuous, slide a sub call
anim.replace structural a sub call
anim.remove structural a sub call
anim.apply structural a sub call
anim.reset structural a sub call
anim.crossfade transition init, transition:
anim.morph transition transition:
anim.push transition init, transition:
anim.cover transition init, transition:
anim.uncover transition init, transition:
anim.wipe transition init, transition:

The Document

animo

animo(body, width: 16cm, height: 9cm, margin: 1cm,
      primitive-duration: 0.4, transition-duration: 0.4, easing: "ease-in-out",
      transition: anim.crossfade())

The shape and the tempo of the deck, applied as a document show rule.

Argument Type Default Meaning
body content the document, given by the show rule
width length 16cm the width of a slide, which is the viewport's width
height length 9cm the height of a slide
margin length 1cm the inset of the body inside the viewport
primitive-duration number 0.4 default seconds of one primitive
transition-duration number 0.4 default seconds of a transition into a slide
easing string "ease-in-out" the timing function both of them follow
transition transition anim.crossfade() the transition of a slide whose init names none
#show: animo.with(width: 16cm, height: 9cm, margin: 1cm)

The two durations and transition are HTML only, because the paged outputs put every state on a separate page with nothing in between. The transition argument takes one of the transitions. The two durations are defaults, and a duration of zero means that kind of motion is not animated unless a primitive or an init states a duration. A reader whose browser asks for reduced motion gets no motion at all.

easing takes one of five names, which are the CSS timing functions of the same name:

Name Moves
"linear" at one speed from beginning to end
"ease" off quickly, then slows down towards the end
"ease-in" off slowly and arrives at full speed
"ease-out" off at full speed and slows down to a stop
"ease-in-out" off slowly, speeds up, and slows to a stop

The HTML presentation takes its <title> from set document(title: ..) and its language from set text(lang: ..), as any typst document exported to HTML does. The description, author and keywords of set document(..) become <meta> elements. In the HTML target, typst refuses a set document rule after the show rule, so these rules come first:

#set document(title: [Animo Tour], author: "A. Author")
#set text(lang: "en")
#show: animo.with(width: 16cm, height: 9cm)

A title that holds markup becomes its plain text.

Taught in Slides and Presenting.

Slides

slide

slide(body, animation: (), canvas: auto, background: none, overlay: none, numbered: true)

One slide of the deck.

Argument Type Default Meaning
body content what is on the slide
animation block of an init and of sub calls () the timeline
canvas auto or (width:, height:) auto the canvas, sized to the content or stated
background none, color or content none the layer behind everything
overlay none, color or content none the layer in front of everything
numbered bool true whether the slide counter counts this slide
#slide(background: navy, animation: anim.init(duration: 0))[= A slide]

How the slide is entered, the gaps around its initial state and whether the handout keeps that state are arguments of anim.init.

Taught in Slides, and canvas: in The Viewport.

tag

tag(name, body, wrap: auto)

Mark a part of a slide so that the timeline can address it by name.

Argument Type Default Meaning
name str what the timeline refers to
body content what is marked
wrap auto, box, block, none, or function auto the container the tag site becomes

A tag's initial state is not an argument. A tag whose first display operation is reveal starts hidden, and one whose first content operation is reset starts removed (see Tags).

#tag("claim")[A claim that a later reveal brings in.]

Which primitives reach which kind of tag site:

Tag site Structural Continuous
ordinary content yes yes
inside math yes yes
a cetz content() element or fletcher node yes yes
content tagged with wrap: none, inside a region yes refused
content tagged with wrap: none, in no region refused refused
a grid.cell or a table.cell that sets more than its body refused refused
an item of a list, an enum or a terms list refused refused
raw cetz draw commands refused refused

The structural primitives are resolved by typst when it renders the slide, so they work wherever a tag can wrap something at all. The continuous primitives are resolved by the browser and need a group to address, which typst emits only for labelled boxes and blocks. A pan(relto: ..) reads a corner of that group, so it is refused on a wrap: none tag too. A wrap: none tag has no box that a change of its content could stay inside, so a structural primitive reaches it only inside a region.

A grid.cell, a table.cell and an item of a list, an enum or a terms list are read by the container they sit in, which never sees them behind a tag site. Write the tag inside the element instead (see Tags). A cell that sets nothing beside its body lays out the same either way, so a tag around it is accepted. A tag around an item is refused whatever the item carries, because the list then takes the whole tag site as the body of a new item, so the tagged item turns into a nested list.

Taught in Tags.

region

region(body, width: auto, height: auto, align: top, clip: auto, name: none)

An area laid out afresh whenever its content changes, inside a footprint that never changes.

Argument Type Default Meaning
body content what is laid out afresh
width auto, length or ratio auto the footprint's width, measured when auto
height auto, length or ratio auto the footprint's height, measured when auto
align alignment top where a state smaller than the footprint sits
clip auto or bool auto true when a size is given, false otherwise
name none or str none makes the footprint a site the continuous primitives reach
#region(height: 3cm)[#tag("claim")[A short claim.]]

Taught in Regions.

Numbering

per-subslide

per-subslide(f, wrap: auto)

Content laid out once per subslide, of which the one belonging to the subslide on screen is shown.

Argument Type Default Meaning
f function called with one dictionary, returns content
wrap auto, box or block auto the container the stack becomes

The subslide info the callback receives:

Key Type What it is
number int the subslide's number within its slide, counting from one
count int how many subslides that slide has
step int the subslide's number within the whole deck, counting from one
steps int how many subslides the whole deck has
handout bool whether the handout keeps the subslide, as init and sub decide

The handout key is the same in every output type, so the HTML presentation and the static presentation can mark the subslides the handout keeps.

Despite their names, step and steps count subslides. The presenter takes steps - 1 steps to get from the first subslide of the deck to the last, which is what a progress indicator measures against.

#per-subslide(it => if it.count > 1 [(#it.number/#it.count)])

Taught in Numbering.

slide-number

slide-number()

The number of the slide it is called on, or none on a slide that numbered: false leaves out. A context function.

#context slide-number()

Taught in Numbering.

slide-count

slide-count()

How many slides of the deck carry a number. A context function.

#context [#slide-number() of #slide-count()]

Taught in Numbering.

Steps

anim.init

init(..transition, duration: auto, wait: none, hold: none, handout: auto)

The initial state of the slide, which is the slide as its body declares it before the first sub. The init call adds no subslide. A timeline holds at most one init, before its first sub.

Argument Type Default Meaning
..transition transition how the slide is entered
duration auto or number auto seconds the transition takes, or the deck's transition-duration
wait none or number none seconds before this slide is entered, or a presenter's click
hold none or number none seconds the initial state stands before the subslide after it
handout auto, true or false auto whether the handout keeps the initial state

Without a transition, the slide takes the default transition of the deck. A duration of zero is a hard cut, whatever the transition. The boundary between two slides takes the init of the slide with the higher number, in both directions. The transition, duration and wait are HTML only.

init(push(direction: btt), duration: 0.6, handout: true)

Taught in Slides, wait and hold in Continuous Animations, and handout in Handouts.

anim.sub

sub(wait: none, hold: none, handout: auto, ..ops)

One subslide: the operations that happen together, and the three things a subslide says about itself.

Argument Type Default Meaning
wait none or number none seconds before this subslide is entered, or a presenter's click
hold none or number none seconds this subslide stands before the one after it
handout auto, true or false auto whether the handout keeps the state this subslide brings about
..ops operations what the subslide does
sub(wait: 2, handout: true, reveal("a"), move("b", dx: 1cm))

Taught in Continuous Animations, and handout in Handouts.

Continuous Primitives

The continuous primitives change how already-rendered content is displayed, so they are smooth in the browser and add no renderings in the paged outputs. Every one of them takes delay: and duration:.

Argument Type Default Meaning
delay number 0 seconds this operation is held back inside its subslide
duration auto or number auto seconds it then takes, or the deck's primitive-duration

anim.reveal

reveal(name, delay: 0, duration: auto)

Make the tag visible. The tag takes the same space whether it is visible or not.

sub(reveal("claim"))

Taught in Continuous Animations.

anim.hide

hide(name, delay: 0, duration: auto)

Make the tag invisible, keeping its space.

sub(hide("claim", duration: 1))

Taught in Continuous Animations.

anim.move

move(name, x: none, y: none, dx: none, dy: none, relto: none,
     delay: 0, duration: auto)

Translate the tag. Each axis takes an absolute position or a shift, never both.

Argument Type Default Meaning
name str the tag to move
x, y length none to that distance from the anchor
dx, dy length none that far from wherever it already is
relto none or str none the tag that is the anchor, else the canvas origin
sub(move("label", relto: "node", dy: -5mm))

Taught in Continuous Animations.

anim.scale

scale(name, f: none, fx: none, fy: none, delay: 0, duration: auto)

Scale the tag about the centre of the box typst laid out for it, which its ink need not fill. On an axis that a move placed with x, y or relto, the tag grows from the start of that box instead, so the corner the move placed stays on its target. The factor is set rather than multiplied into what is already there, and an axis the call does not mention keeps the factor it had.

Argument Type Default Meaning
name str the tag to scale
f number or ratio none one factor on both axes
fx, fy number or ratio none one factor per axis, not with f
sub(scale("figure", f: 1.5))

Taught in Continuous Animations.

anim.pan

pan(x: none, y: none, dx: none, dy: none, relto: none, delay: 0, duration: auto)

Move the viewport over the canvas. It addresses the slide rather than a tag, and reads the same arguments move does. Positive values move the viewport right and down, so the content moves left and up.

sub(pan(relto: "details"))

Taught in The Viewport.

Structural Primitives

The structural primitives change what typst lays out, so each of them starts a new epoch. All four take the same delay: and duration: as the continuous primitives, where they time the crossfade of the region that changed.

All four also take transition:, which says how the region that changed crosses the boundary. The transition argument defaults to auto, which is the crossfade whatever the default transition of the deck is, and it also takes the transitions crossfade() and morph(). The other transitions move a whole slide and are refused here. A duration of zero is a hard cut of the region. Two operations that change one region at one boundary have to name the same transition, as they have to agree about their timing. A region inside another region crosses the boundary together with the outer region, so two operations that change two regions inside one region count as changing one region here. The transition argument is HTML only, because two pages have nothing between them.

anim.replace

replace(name, body, delay: 0, duration: auto, transition: auto)

Lay out body at the tag site instead of what is there, keeping the wrappers apply put around it. The body may be a trailing content block.

sub(replace("claim")[The second answer.])

Taught in Structural Animations.

anim.remove

remove(name, delay: 0, duration: auto, transition: auto)

Lay out nothing at the tag site, keeping the wrappers.

sub(remove("caveat"))

Taught in Structural Animations.

anim.apply

apply(name, delay: 0, duration: auto, transition: auto, ..fns)

Wrap what is laid out at the tag site in each function, the last one outermost. Functions only: a named style property, as in apply("x", fill: red), is refused.

sub(apply("claim", text.with(fill: red), strong))

Taught in Structural Animations.

anim.reset

reset(name, delay: 0, duration: auto, transition: auto)

Back to the body as written, with every wrapper dropped.

sub(reset("claim"))

Taught in Structural Animations.

Transitions

A transition says what crossing a boundary looks like, and nothing about how long it takes. The call that causes the crossing states the time: init for a slide and the structural primitive for a region. A transition is written in three places:

  • as the first argument of init, for the boundary into a slide;
  • as transition: of a structural primitive, for a region;
  • as transition: of animo, for every slide whose init names none.

The direction parameter is ltr, rtl, ttb or btt, and gives the direction of travel on a forward step. A backward step travels the other way.

Transition Slide Region
anim.crossfade yes yes
anim.morph no yes
anim.push yes no
anim.cover yes no
anim.uncover yes no
anim.wipe yes no

anim.crossfade

crossfade()

The outgoing content fades out while the incoming content fades in.

anim.morph

morph()

Content that both versions of a region share moves from its old place to its new place, and the rest fades out and in where it is. A tag moves as one, unless the primitive changes that tag. The letters, shapes and images outside a tag are matched one by one by their shape. The init call and the deck's transition: refuse morph(), because a morph carries a region across a boundary inside a slide.

sub(replace("eq", transition: morph())[$ (a + b)^2 = a^2 + 2 a b + b^2 $])

Taught in Morphs.

anim.push

push(direction: rtl)

The incoming slide moves in from one edge and moves the outgoing slide out at the opposite one.

anim.cover

cover(direction: rtl)

The incoming slide moves in from one edge over the outgoing slide, which stays where it is.

anim.uncover

uncover(direction: rtl)

The outgoing slide moves out at one edge over the incoming slide, which stays where it is.

anim.wipe

wipe(direction: ltr)

The incoming slide is shown behind an edge that travels across the outgoing slide.

Taught in Slides.

Output Types

output-type

output-type()

The output type being compiled: "html" for the HTML presentation, "presentation" for the static presentation and "handout" for the static handouts. A context function. The paged strings are the values that --input animo= takes.

#context if output-type() == "html" [Use the arrow keys to step through the talk.]

Taught in Output Types.

animo-logo(fill: auto, ..arguments)

The logo of Animo, as an image in any color.

Argument Type Default Meaning
fill auto or color auto the color of the logo, the text color when auto
arguments arguments passed on to image, such as height, width or alt

The fill has to be a single color, because the logo is an SVG image with one fill attribute.

#animo-logo(fill: rgb("#008ba8"), height: 2cm)

Taught in The Animo Logo.

made-with-animo

made-with-animo(fill: auto, height: 2em)

A badge with the logo beside the words "made with Animo" on two lines. The word "Animo" is set larger, so that it is as wide as "made with" above it.

Argument Type Default Meaning
fill auto or color auto the color of the logo and the words, the text color when auto
height length 2em the height of the logo, which is also the height of the badge
#place(bottom + right, made-with-animo(height: 1cm))

Taught in The Animo Logo.

Command Lines

typst compile --format html --features html talk.typ talk.html
typst compile --input animo=presentation talk.typ talk-presentation.pdf
typst compile talk.typ talk-handout.pdf

Taught in Output Types.