Hacking Typst: Better Vertical Balance in Two-Column Pages
While refining the Typst source for my Essential R Cheatsheets, I kept noticing a small but persistent typesetting problem. The development version of Typst can already balance content across columns, yet the two columns do not always finish at quite the same visual height. On a dense page, even a few points of unused space at the bottom can be surprisingly noticeable.
The gap that bothered me
Page 50 of the working book is a good example. In the original layout, the right column extends visibly farther down, leaving an awkward strip of white space below the left column.

My immediate reaction was: this should be easy to prevent, so why does Typst not do it automatically?
The page contains many ordinary vertical gaps: between paragraphs, around headings and blocks, and between individual lines. Instead of collecting the entire mismatch in one conspicuous space at the bottom, Typst could distribute it across all those gaps. Each adjustment would be tiny—ideally too small to notice on its own.
I did not know whether this was typographically unorthodox, whether it would create awkward edge cases, or whether the extra layout work would compromise Typst’s blazing speed. There was only one sensible way to find out: try it.
Choosing a sensible target
The algorithm does not blindly stretch every column to the bottom of the page. Each column reports the range of heights it can reach within the configured limits. Typst then chooses a common reachable target. If perfect alignment is impossible, it chooses the target that leaves the smallest remaining difference. Final partial pages and explicit breaks keep their natural height.
That distinction matters. Filling every column to the bottom would make short chapter endings look strangely stretched. The goal is not to fill space at any cost, but to improve alignment wherever the available, visually safe adjustments make that possible.
Speed
In a quick warm benchmark of the complete book, I could not measure a meaningful slowdown compared with regular Typst. That was important to me: Typst’s speed is the main reason I use it.
Scope
The mechanism is not inherently limited to two-column documents. It can also justify full pages in a single-column layout. Still, the benefit is most obvious when two neighboring columns should end together.
Installing the experiment on Arch Linux
I added a PKGBUILD that compiles the flex-spacing-prototype branch and installs it as a drop-in replacement for Typst. It deliberately conflicts with the official typst package so that Pacman cannot leave two different /usr/bin/typst binaries on the system.
Download the file into an empty directory, inspect it, and build it with makepkg:
mkdir typst-flex-spacing-build
cd typst-flex-spacing-build
curl -O https://johannestitz.com/post/2026-08-09-typst-vertical-justification/PKGBUILD
less PKGBUILD
makepkg -siThe build follows the experimental Git branch, so rebuilding the package later will pick up newer commits. To return to the official Arch package, run:
sudo pacman -S typstA prototype, for now
This is deliberately still an experiment. The implementation and its tests are available on the flex-spacing-prototype branch of my Typst fork. I want to try it on more real documents before settling on an API and deciding whether it is ready for a pull request—if it should become one at all.
The book behind the example
If the example made you curious about the content, Essential R Cheatsheets collects the R and statistics references I actually want within reach while working. The current edition is available in several print formats on the Amazon series page.
