The previous post wrapped up two commonly-used markup features — code blocks and math formulas — covering syntax highlighting for inline and block code, and the rules for how formulas and variables get interpreted in math mode. This post moves up a level to handle the page itself: how big the paper is, how much margin to leave, whether to split into columns, and how to place page numbers and headers/footers — the basic settings you can’t avoid when laying out a document.
Paper size and orientation comes first, covering how to pick a standard size and how to adjust for a custom size or landscape orientation; then page margins, covering the difference between a uniform setting and per-side settings; then columns, letting content automatically flow into a multi-column layout; the page numbers section covers the basic format and custom placement; and it all wraps up with headers and footers, demonstrating how to add fixed content to the top and bottom of every page. The goal is to take a Typst document from plain body text to something that looks like a proper formal document.
Paper Size and Orientation
The first thing to decide when writing a document is what size of paper it’ll ultimately be printed on, and whether it’s portrait or landscape. Typst splits this into two parts: a built-in table of standard paper sizes you can apply directly, and full support for custom width and height — both handled through the same page function.
Standard Paper Sizes
Typst has a large built-in table of standard paper sizes, applied directly via #set page(paper: "...") with a name string — no need to look up obscure size conversions yourself:
| Name | Code | Dimensions (W x H) |
|---|---|---|
| A3 | a3 |
297mm x 420mm |
| A4 | a4 |
210mm x 297mm |
| A5 | a5 |
148mm x 210mm |
| A6 | a6 |
105mm x 148mm |
| B5 (ISO) | iso-b5 |
176mm x 250mm |
| US Letter | us-letter |
215.9mm x 279.4mm |
| US Legal | us-legal |
215.9mm x 355.6mm |
1 | #set page(paper: "a4") |
Typst’s default paper is already A4, so there’s no need to set this explicitly if that’s what you want. More available paper codes can be found in the official Typst documentation, and the actual use cases for each size can be found in this list of paper sizes.
Custom Sizes and Landscape
If none of the standard sizes fit your needs (say, for a business card or a poster), you can specify dimensions directly with width and height:
1 | #set page(width: 9cm, height: 5.5cm) |
For a landscape layout, there’s no need to swap the width and height numbers yourself — just add flipped: true, and Typst will rotate the specified paper size into landscape:
1 | #set page(paper: "a4", flipped: true) |
A Worked Example
Using the page function to place two different page settings in the same document: the first page is A4 in the default orientation, and the second switches to B5 in landscape:
1 | #set text(font: ("Libertinus Serif", "PingFang TC"), size: 12pt) |
Compiling with typst compile produces two pages with different sizes and orientations:


Page Margins
Once the paper size is decided, the next thing is how much space to leave between the body area and the paper’s edges — the margins. The diagram below lays out the terminology for page geometry:

On the left, paper height and paper width correspond to the paper size set in the previous section; subtract the top, bottom, left, and right margins from that, and what’s left — the body area (height and width) — is exactly the range the margin parameter in this section deals with. On the right, the head and foot areas are covered separately in the Headers and Footers section further down; text height and text width are about the paragraph’s own font size and line spacing, which will be expanded on in a later post about paragraph settings.
The odd one out is the marginal note on the far right (along with marginparsep and marginparwidth) — this is the common LaTeX convention of reserving a side column next to the body for notes, but Typst’s page function has no corresponding built-in parameter for it; it has to be placed manually with the place function instead. That’s covered in a later post on absolute positioning, so it’s skipped here.
Uniform Margins
The simplest case: pair margin with a single value, and all four sides get the same margin:
1 | #set page(margin: 2.5cm) |
Without an explicit setting, Typst’s default margin value is auto, which picks a ratio automatically based on the paper size rather than a fixed number.
Per-side Margins
margin can also take a dictionary, specifying top, bottom, left, and right individually, or x and y to set the horizontal and vertical directions at once — any side left unfilled can be backfilled with a default via rest:
1 | #set page(margin: (top: 3cm, bottom: 2cm, x: 2.5cm)) |
If a document is meant to be printed double-sided and bound (compare inside margin and outside margin in the diagram above), the binding side usually needs extra space — in that case, inside and outside paired with the binding parameter fit better than left and right:
1 | #set page( |
binding specifies which side the binding is on; inside then automatically maps to whichever side is closer to the binding, and outside to the other side. That way odd and even pages automatically mirror their margins, without having to manually check which page needs which value.
A Worked Example
The example below uses a red box flush against the body area to actually draw out how the inside and outside margins mirror between odd and even pages:
1 | #set text(font: ("Libertinus Serif", "PingFang TC"), size: 11pt) |
After compiling, you can see: the first page (odd) has a wider left margin, and the second page (even) switches to a wider right margin — the body areas on the two pages mirror each other left-to-right:


Columns
Reports and handouts sometimes call for a newspaper-style multi-column layout. Typst offers two ways to do columns: applying it to the whole page, or scoping it to just one section of content while the rest stays single-column.
For full-page columns, use the columns parameter on the page function — fill in a number to decide how many columns, and content automatically flows to fill each one in order:
1 | #set page(columns: 2) |
To scope columns to just one section of content while leaving the rest as single-column, wrap that section in the standalone columns function instead1, and gutter can adjust the spacing between columns (the default is 4% of the page width):
1 | #columns(2, gutter: 12pt)[ |
Worth noting: the first argument to the columns function is the column count, and its default is 2; without manually controlling it with colbreak(), content fills up one column in its original order before moving to the next.
A Worked Example
Write an example condensed onto a single A4 page: the top half is a single-column title and abstract, and the bottom half’s body text is split into two columns with columns — pretty close to a typical paper layout:
1 | #set text(font: ("Libertinus Serif", "PingFang TC"), size: 10.5pt) |
After compiling with typst compile, the whole thing fits exactly on one A4 page:

Page Numbers
Once a document has more than a few pages, page numbers are basically essential, letting readers know which page they’re on and how many pages there are in total. Typst keeps this in the page function too, with format and placement each controlled by their own parameter.
Basic Page Number Format
The numbering parameter controls whether page numbers show up and what format they use — the pattern-string rules are the same ones used for heading numbering in Day 04:
1 | #set page(numbering: "1") |
To show both the current page and total page count, use the "1 / 1" pattern, and Typst automatically computes the total and fills it in:
1 | #set page(numbering: "1 / 1") |
Just like heading numbering, 1 can be swapped for a (letters), i (Roman numerals), or other counting symbols, or combined into a custom format like Page 1. If numbering isn’t set, page numbers are hidden by default.
Custom Page Number Placement
By default, page numbers print centered in the footer. To change the position, use the number-align parameter. It takes a vertical direction (top for header, bottom for footer) combined with a horizontal direction (left, center, right) via +, giving six possible positions — the same concept as the six-cell grid in LaTeX’s fancyhdr:
1 | #set page( |
That switches the page number from the default centered footer to the top-right of the header.
A Worked Example
Continuing with the Typst introduction example from the Columns section, add page numbers, changing the format to Page x of x and placing it at the bottom-right of the footer:
1 | #set text(font: ("Libertinus Serif", "PingFang TC"), size: 10.5pt) |
Here, numbering isn’t a pattern string but a function: it takes the current page current and total page count total as two parameters, and returns whatever content you want, letting you assemble a format like Page x of x without being limited to the built-in pattern syntax. After compiling, the page number shows up at the bottom-right of the footer:

Headers and Footers
Page numbers are just the most common kind of content in a footer (or header) — the page function can actually fully customize what goes in the header and footer, not limited to numbers.
The header and footer parameters let you insert arbitrary content, with an effect similar to setting numbering directly, but you can put in titles, section names, and other static text:
1 | #set page( |
To have the header or footer show different content depending on the page number (say, odd vs. even) — a common convention in books is putting the book title on odd pages and the chapter name on even pages — you need context paired with counter(page) to read the current page number, then calc.rem to check odd or even:
1 | #set page( |
Worth noting: if header (or footer when number-align is set to top-aligned) has an explicit value, numbering gets ignored; but as long as the two are aligned to different positions (say, a title in the header and the page number left in the footer), they can coexist without overwriting each other.
A Worked Example
Continuing with the Typst introduction example, this time adding a header that alternates between odd and even pages. The body also gets two more sections (Comparison with Other Tools, Further Reading) — with the extra content, it naturally overflows onto a second page, which is exactly what lets us see the odd/even header difference:
1 | #set text(font: ("Libertinus Serif", "PingFang TC"), size: 10.5pt) |
There’s no manual pagebreak() here: it’s purely that the content inside columns grew past what fits on one page, so it naturally overflows to the next, and the columns layout just continues right along with it. After compiling, there are two pages total: the first is an odd page, with the document title printed right-aligned in the header; the overflow onto the second page is an even page, with the header switching to left-aligned Typst Tutorial; the page number in the footer shows up correctly on both pages, without being covered by the header:


Summary
This post covered paper size and orientation — the standard size table, custom width/height, and landscape with flipped; page margins — uniform settings, per-side settings, and inside/outside for binding; columns, in both full-page and scoped forms; page numbers, from the basic format to customizing all six placements; and finally headers and footers, demonstrating both static content and odd/even alternation. Put these settings together, and a Typst document finally has the skeleton a printed document is supposed to have.
The next post moves on to the #set rule itself, formally introducing this core concept that runs through Typst’s entire style system — the #set text and #set page usages scattered across earlier posts will get a more complete explanation.
See you next time~
1. Once columns narrow things down, CJK text layout gets more sensitive to font choice: testing showed that without an explicit font (like the ("Libertinus Serif", "PingFang TC") used throughout this post), the default CJK font the system picks automatically can, in narrow columns, miscalculate line spacing and cause whole paragraphs to overlap. Setting an explicit font fixed it. For columns and narrow layouts in general, it’s worth making a habit of setting the font list up front to avoid this kind of layout breakage. ↩