Semantic layouts

The contents below link to each definition. Function entries show the signature, then a description, then the parameters with their types and defaults; variable entries show the declared type.

Creates a validated author record for setup(authors:) and layouts.title(authors:).

author(
  name,
  affiliations: (),
  email: none,
  orcid: none,
  corresponding: false
) -> dictionary
Description

A name on its own needs no record at all. authors: takes content or a string wherever it takes a record, so authors: [Ada Lovelace] and authors: ([Ada Lovelace], [Charles Babbage]) are both complete author lists. Reach for author() when a name carries more than itself:

#let ada = mosaic.layouts.author(
  [Ada Lovelace],
  affiliations: ([Analytical Society], [University of London]),
  email: "ada@example.org",
  orcid: "0000-0002-1825-0097",
  corresponding: true,
)

Affiliations

An affiliation is the institution itself: content or a non-empty string. Two authors share one legend number exactly when they give the same affiliation, so bind a shared institution once and reuse the binding:

#let lon = [University of London]
#let ada = mosaic.layouts.author([Ada Lovelace], affiliations: (lon,))
#let bab = mosaic.layouts.author([Charles Babbage], affiliations: (lon,))

The academic title variant renders these as superscript numbers over a numbered legend. Compact variants list them without numbering.

Validation

Values are checked at construction rather than at render time:

Arguments
namecontent | str
The author’s name, as the sole positional argument.
affiliationsarray
Array of institutions, as content or non-empty strings, in the order they should be listed for this author.
emailstr | none
Contact address, shown on the academic title variant and linked as a mailto:. Independent of orcid.
orcidstr | none
ORCID iD in 0000-0000-0000-0000 form, rendered as a linked ORCID label beside the name on every title variant. Independent of email.
correspondingbool
Whether to mark this author as the corresponding one, with an asterisk beside the name and on the contact line. Requires email or orcid.

Creates a conventional header, body, and footer grid recipe.

content(variant: "header-body-footer", columns: 1, tracks: auto) -> dictionary
Description

This is the ordinary slide layout, and the one automatic level-two headings resolve to. It builds a vertical Mosaic split whose body child is a horizontal split of plain cells.

#mosaic.slide(
  layout: mosaic.layouts.content(variant: "header-body", columns: 2),
  [== Two columns],
  [Left body],
  [Right body],
)

Cells

The surrounding mosaic.slide fills cells in traversal order:

A setup-level content: (footer: ...) default can satisfy the footer, so a positional slide may omit that final block.

Variants

Labels

Every resolved cell carries a label, so appearance comes from native Typst rules:

Styling

The layout is purely structural, so its looks come from rules on those labels.

#show label("mosaic-cell-header"): set block(fill: luma(240))

The header cell carries no special typography of its own. Put a native level-two heading in its content to style it as a heading and register it with outlines.

Arguments
variantstr
Structural arrangement: body, header-body, body-footer, or header-body-footer.
columnsint
Number of body columns, and therefore the number of body blocks the slide must supply. Must be a positive integer.
tracks

auto | array
Native Typst track sizes for the body columns, one per column. auto splits the body evenly.

mosaic.layouts.content(columns: 2, tracks: (2fr, 1fr))

Creates an image-first grid recipe.

image(
  image,
  variant: "figure",
  caption: none,
  fit: auto,
  tracks: auto
) -> dictionary
Description

This is the image-first counterpart to layouts.content: the picture is the argument rather than slide content, and the text regions arrange around it. The surrounding mosaic.slide fills only the text cells.

#mosaic.slide(
  layout: mosaic.layouts.image(
    path("chart.webp"),
    caption: [Revenue by quarter],
  ),
  [== Results],
)

Variants

Captions

A caption composes a native Typst figure around the picture, so it takes the deck’s own show figure.caption styling and figure numbering. Switch the numbering off with an ordinary set figure(numbering: none). Captions are accepted by the figure variant only.

Labels

Every resolved cell carries a label, so appearance comes from native Typst rules:

Styling

The layout is purely structural, so its looks come from rules on those labels. The full variant inherits the surrounding native text color, so quiet the photograph with the image dictionary’s scrim key and override the cell’s text fill.

#show label("mosaic-cell-body"): set text(fill: white)
#mosaic.slide(
  layout: mosaic.layouts.image(
    (path: "photo.webp", scrim: black.transparentize(55%)),
    variant: "full",
  ),
  [== Full bleed],
)
Arguments
imagecontent | str | path | dictionary
The picture the slide is built around, as the sole positional argument. Give a path, ready-made content, or a dictionary whose scrim key paints a layer over the picture and under any text composed on top of it.
variantstr
Structural arrangement of picture and text: figure, full, left, right, top, or bottom.
captioncontent | none
Caption composed below a figure picture. Rejected by the other variants.
fit

auto | str
How the picture fills its region.

  • "contain": fit the whole picture inside the region. The figure default, since a chart must never be cropped.
  • "cover": fill the region, cropping the overhang. The default for every other variant.

auto picks the per-variant default above.

tracksauto | length | ratio | relative | fraction | array
Sizes the split of a directional variant, and is rejected by figure and full. One native Typst track size answers “how much room does the picture get” and is side-independent, so left and right stay mirror images without reordering anything; the text region takes the remaining 1fr. An array of two is in visual order instead, and must be mirrored by hand when the variant flips.

Creates a presentation title grid.

title(
  title: auto,
  subtitle: auto,
  date: auto,
  image: none,
  variant: "ruled",
  position: auto,
  authors: auto,
  tracks: auto,
  rule: auto,
  accent: auto
) -> dictionary
Description

The layout supplies every cell’s content itself, so the surrounding mosaic.slide consumes no slide bodies.

#show: mosaic.setup.with(
  title: [Tree-based slide grids],
  subtitle: [A layout model for Typst],
  authors: [Ada Lovelace],
  date: [2026-08-03],
)

#mosaic.slide(layout: "title", variant: "centered")

Inheritance

Each of title, subtitle, authors, and date defaults to auto, which takes the value configured on setup. To override an inherited value:

Variants

Text variants:

One image variant, which requires image and reads position:

A full-slide photographic title is not a variant: give the slide a background: plane and compose the type yourself, reading the deck’s own metadata back through info().

To invert any of these, with the slide ground in the deck’s text color and the type knocked out, pass invert: true on the slide rather than picking a variant; inversion is a polarity, not a structure.

Authors

Every variant accepts the same authors, written in whichever of three spellings fits the deck: one name as content or a string, an array of names, or an array of records built with layouts.author for the authors that carry affiliations, an ORCID iD, or an address. Names and records mix freely in one array. Every variant renders every author field through the same tiers: a byline of names with linked ORCID labels, superscript affiliation numbers, and the corresponding asterisk, then one fine-print line per kind of information: the numbered affiliation legend, the contact addresses, the date. Kinds never share a line, and the superscript markers appear exactly when the deck names more than one institution.

Labels

Every resolved cell carries a label, so appearance comes from native Typst rules:

One further label is not a cell: the display line of the title stack carries mosaic-title-display, which is where a theme states the title’s display size.

Styling

The layout is structural. A rule on <mosaic-cell-title> reaches the whole composed stack: title, subtitle, and details alike. Recoloring it is what light-on-dark compositions over a photograph need.

#show label("mosaic-cell-title"): set text(fill: white)
#mosaic.slide(
  layout: "title",
  background: mosaic.components.image("cover.webp", scrim: black.transparentize(55%)),
)

Sizing it works the same way, because the display line carries its own <mosaic-title-display> label and the theme’s display size lands there rather than on the cell. The tiers below are ordinary ems of the cell, so one rule scales the stack as a unit and the proportions hold. That is how to ask for quiet type in the corner of a photograph.

#show label("mosaic-cell-title"): set text(size: 0.45em)

A theme states the display size on the inner label instead, which leaves the outer one free for the deck to scale:

#show label("mosaic-title-display"): set text(size: 2em, weight: "semibold")
Arguments
titleauto | content | str
Title text. auto inherits setup(title:).
subtitleauto | content | str | none
Subtitle set tight below the title. auto inherits setup(subtitle:); none suppresses it.
dateauto | content | str | none
Display date joined into the fine-print details line. auto inherits setup(date:); none suppresses it.
imagenone | content | str | path | dictionary
The picture used by the image variant, and rejected by the others. Give a path, ready-made content, or a dictionary whose scrim key quiets the photograph enough to read text over it, as in (path: "cover.webp", scrim: black.transparentize(55%)).
variantstr
Structural arrangement: ruled, centered, bordered, kicker, panel, academic, or image.
positionauto | str
Where the image variant’s picture sits, and rejected by the others: left, right, top, or bottom, for a full-bleed picture beside or above the title stack. auto means left.
authorsauto | content | str | array
One name, or an array of names and records created with layouts.author. auto inherits setup(authors:); () suppresses an inherited list.
tracksauto | length | ratio | relative | fraction | array
Sizes the image variant’s split, and is rejected elsewhere. One native Typst track size sizes the picture and is side-independent, so the left and right positions stay mirror images; the title region takes the remaining 1fr. An array of two is in visual order instead, and must be mirrored by hand when the position flips. auto gives the picture the smaller share.
ruleauto | bool
Whether to draw the variant’s structural mark: the ruled full-width rule, the bordered border, or the kicker opening rule. On the image variant it draws the short accent rule of the compact stack instead. auto draws the structural marks and omits the accent rule on the image variant, where the photograph already does that work.
accentcolor | auto
Color of the variant’s structural mark. auto uses the deck’s text color for the marked text variants (bordered, kicker) and the semantic accent for the image variant’s short rule.

Creates a section divider grid.

section(
  subtitle: none,
  number: none,
  image: none,
  variant: "plain",
  accent: auto,
  tracks: auto
) -> dictionary
Description

The section cell’s text is the slide’s own content, so the surrounding mosaic.slide supplies one block. Automatic level-one headings resolve to this layout.

#mosaic.slide(
  layout: "section",
  number: [02],
  subtitle: [How the grid resolves],
)[Structure]

Variants

Every image variant requires image. The designed text variants (every variant but plain and the image ones) treat an omitted number as the automatic section counter, so they need no argument in the ordinary case.

Labels

Every resolved cell carries a label, so appearance comes from native Typst rules:

Styling

The layout is structural. The centered arrangement and title typography come from the <mosaic-cell-section> label rules setup emits. Over a photograph the text inherits the surrounding native text color, so quiet the picture with the image dictionary’s scrim key and override the cell’s text fill.

#show label("mosaic-cell-section"): set text(fill: white)
#mosaic.slide(
  layout: "section",
  variant: "image-background",
  image: (path: "cover.webp", scrim: black.transparentize(55%)),
)[Structure]
Arguments
subtitlecontent | str | none
Optional subtitle set below the section title.
numbercontent | str | none
Optional section number or label. plain and the image variants set it above the title and omit it when none; the designed text variants build their composition around it and read the automatic section counter when it is none.
imagenone | content | str | path | dictionary
The picture used by the image variants, and rejected by the others. Give a path, ready-made content, or a dictionary whose scrim key quiets the photograph enough to read text over it.
variantstr
Structural arrangement: plain, image-left, image-right, image-top, image-bottom, or image-background.
accentcolor | auto
Color used by the optional section number. auto inherits the semantic muted color resolved by setup, so numbers stay subordinate to the title; pass a color to override.
tracksauto | length | ratio | relative | fraction | array
Sizes the split of a directional image variant, and is rejected by the others. One native Typst track size sizes the picture and is side-independent, so image-left and image-right stay mirror images; the section region takes the remaining 1fr. An array of two is in visual order instead.