Skip to content

Load fonts and fit the grid

You will size the grid using your chosen font. Start with a font URL your page is allowed to fetch and a sized host.

fonts.ts
import { Terminal } from 'ghostty-webgpu'
export async function mountWithFont(host: HTMLElement, fontUrl: string) {
const face = new FontFace('Terminal Mono', `url(${fontUrl})`)
document.fonts.add(await face.load())
const terminal = await Terminal.create({
appearance: { font: { family: '"Terminal Mono", monospace', size: 14 } },
})
await terminal.open(host)
terminal.writeln('Font loaded before measuring the grid.')
return () => terminal.dispose()
}

The example registers a FontFace, waits for it to load, then creates the terminal with that family. CSS @font-face works too; await document.fonts.load before opening. Worker terminals load their own faces.

Call setFont with a partial font object to change family, size, lineHeight, weight, boldWeight or letterSpacing. lineHeight multiplies the measured font box and must be at least 1. Font size describes the em size; the measured row can be taller.

The fitter measures the font in CSS pixels, rounds its device-pixel geometry, then fits the host. Let the terminal perform this calculation so the session and renderer agree.

libghostty-vt determines cell widths. The browser’s fallback fonts determine glyph appearance. Applications enable grapheme clustering with mode 2027. With that mode enabled, a ZWJ sequence such as 👩‍💻 occupies two cells. With it off, native default widths apply. The renderers use the same native cell ownership.

Wait for the face before opening, and use the exact registered family. Check CORS and network responses for the font URL.

Font box metrics include ascent and descent. Check lineHeight and the actual loaded face. The repository’s font geometry note explains the rounding formulas.

Next, apply a theme.