Skip to content
BoWen Chai's Notes
Go back

Useful Typst Snippets: CTyp and CeTZ

Updated:
Edit page

This page explains how to set up Chinese typography with CTyp 0.3.1 and how to draw a diagram with CeTZ 0.5.2. The old one-off CJK rules remain at the end as legacy snippets.

All examples on this page are compile-tested with Typst 0.15.1. The package versions are also pinned so that the examples stay reproducible. CTyp 0.3.1 requires Typst 0.14.1 or newer, while CeTZ 0.5.2 requires Typst 0.14.0 or newer.

Table of Contents

Open Table of Contents

Set up Chinese typography with CTyp

CTyp provides a document-wide Chinese typesetting setup. In addition to selecting CJK fonts, it sets the document language to Chinese, justifies paragraphs, adds a two-em first-line indent, fixes list-marker alignment, and removes unwanted spaces between CJK characters split across source lines.

Check Typst and the fonts first

Typst downloads a @preview package automatically when it first sees the import. CTyp does not bundle the fonts themselves, so check what the compiler can see before choosing a font preset:

typst --version
typst fonts

The first command should report typst 0.15.1. If it reports an older version, update the CLI before using these examples.

Use the exact family names printed by typst fonts when defining a custom font set. The two most useful built-in CTyp presets are:

CTyp also includes source, windows, fangzheng, and huawen presets, but those work only when their corresponding fonts are available to Typst.

If all four Fandol families are available, the default configuration is the shortest setup:

#import "@preview/ctyp:0.3.1": ctyp

#let (ctypset, cjk) = ctyp()
#show: ctypset

= 中文标题

这是正文。CTyp 会应用中文字体、两字宽首行缩进和其他基础排版规则。

#(cjk.hei)[这里显式使用黑体。]

ctyp() returns two values. ctypset is the show rule that applies the document theme; cjk is a dictionary of helpers such as song, hei, kai, and fang, depending on the selected font set. A helper stored in a dictionary must be called as #(cjk.hei)[...], with parentheses around the field access.

Place #show: ctypset after the CTyp configuration and before the document body that should receive it.

Typst web app or local Noto setup

CTyp 0.3.1 adds title-font support, but its released Noto preset omits the required title mapping. This remains necessary with Typst 0.15.1. Without the override below, the preset fails with dictionary does not contain key "title". This setup supplies the missing mapping and also shows optional Latin fonts and heading numbering:

#import "@preview/ctyp:0.3.1": ctyp

#let (ctypset, cjk) = ctyp(
  fontset-cjk: "noto",
  font-latin: (
    serif: "Libertinus Serif",
    mono: "DejaVu Sans Mono",
  ),
  font-cjk-map: (
    title: (cjk: "song:bold", latin: "serif"),
  ),
  heading-numbering: "1.1",
)
#show: ctypset

#set document(title: [中文文档])

= 第一章

正文使用 Noto Serif CJK SC,*粗体*使用 Noto Sans CJK SC。

The other non-Fandol presets in CTyp 0.3.1 also lack a title entry. Apply a matching font-cjk-map.title override when using one of them. Remove the workaround after upgrading only when the newer preset defines that mapping.

CTyp improves common Chinese layouts, but it is not a complete implementation of every Chinese typesetting rule. Keep document-specific adjustments close to your template instead of assuming that the package handles every edge case.

Draw diagrams with CeTZ

The package is spelled CeTZ and imported as cetz; ctez is a common transposition. CeTZ provides a drawing canvas with an API inspired by TikZ and Processing.

Start with a scoped canvas

Use the package namespace for the canvas, then import drawing functions only inside its code block:

#import "@preview/cetz:0.5.2"

#cetz.canvas({
  import cetz.draw: *

  circle((0, 0))
  line((0, 0), (2, 1))
})

Keeping import cetz.draw: * inside the canvas matters because CeTZ exports names such as line that would otherwise shadow Typst’s built-in functions. The canvas grows to fit its drawing. By default, one coordinate unit is one centimetre, the x-axis points right, and the y-axis points up. Pass length: to cetz.canvas when a different scale is needed.

Connect named elements with anchors

For diagrams that may change, name elements and connect their anchors instead of hard-coding every line endpoint:

#import "@preview/cetz:0.5.2"

#cetz.canvas({
  import cetz.draw: *

  set-style(content: (
    frame: "rect",
    padding: .18,
    fill: rgb("e8f0fe"),
    stroke: rgb("2457c5"),
  ))

  content((0, 0), [Typst], name: "source")
  content((3, 0), [PDF], name: "output")
  line("source.east", "output.west", mark: (end: ">"))
})

Here, content creates two framed nodes, source.east and output.west refer to their border anchors, and mark: (end: ">") adds the arrowhead. set-style supplies defaults for later elements; arguments passed directly to a drawing function override those defaults.

For more complex work, use the CeTZ manual for coordinate systems, anchors, marks, transformations, and reusable styles. Use a focused library such as cetz-plot for plots rather than rebuilding a charting layer from primitives.

Legacy manual CJK snippets

These small rules predate CTyp. They are still useful when adding a package is unnecessary, but they cover only one concern each and do not form a complete Chinese typesetting setup.

Set a font for Han characters

This show rule applies a Simplified Chinese Noto serif font to runs of Han characters. The named font must be visible in typst fonts.

#show regex("\p{sc=Hani}+"): set text(lang: "zh", font: "Noto Serif CJK SC")

Indent paragraphs by two CJK character widths

Measuring two representative CJK characters is more robust than hard-coding a point value because the indent follows the active font and size:

#context {
  let indent-width = measure("空格").width
  set par(first-line-indent: indent-width)
  // Content goes here.
}

Prefer CTyp for a Chinese document-wide baseline. Keep these legacy snippets for isolated content or for templates that intentionally manage every other typographic rule themselves.


Edit page
Share this post:

Previous Post
Blender 5 Film Flash, Part 1: Place and Shape the Light
Next Post
胶卷曝光速查:不同拍摄场景该怎样设置 EI