# Typography

> Compare font pairings, and set your own.

Source: https://aymericchaverot.github.io/zenith-docs/customization/typography/

ZenithDocs self-hosts its fonts through the Astro Fonts API: nothing is fetched from a third party at runtime, and no layout shift is paid for it. Seven presets are available through the `fonts` option, and only the one you pick is downloaded.

```js title="astro.config.mjs"
zenith({
  title: 'My Docs',
  fonts: 'literata', // [!code highlight]
});
```

## Try a preset

The buttons below swap the fonts of this whole page, chrome included, so you can judge a preset in place rather than on a specimen sheet. Scroll around after switching.

<FontPicker />

They work by setting `--font-body`, `--font-mono` and `--font-display`, which is exactly what you would write in a `customCss` file to use a family of your own.

| Preset         | Headings              | Body                  | Code            |
| -------------- | --------------------- | --------------------- | --------------- |
| `instrument`   | Instrument Serif      | Instrument Sans       | Martian Mono    |
| `geist`        | Geist                 | Geist                 | Geist Mono      |
| `newsreader`   | Newsreader            | Onest                 | IBM Plex Mono   |
| `schibsted`    | Schibsted Grotesk     | Schibsted Grotesk     | JetBrains Mono  |
| `space`        | Space Grotesk         | Space Grotesk         | Space Mono      |
| `atkinson`     | Atkinson Hyperlegible | Atkinson Hyperlegible | JetBrains Mono  |
| `literata`     | Literata              | Literata              | IBM Plex Mono   |

The presets with a serif use it for `h1` and `h2` only. Lumos keeps one family token per heading level, so `h3` and below stay on the body font, where a high-contrast serif would become hard to read at small sizes.

### A heading three, to judge the smaller sizes

A paragraph of running text, long enough to show how the pairing behaves over several lines: the width of the lowercase, the shape of the numerals like 0123456789, and how it handles `inline code` and [a link](/customization/theming/) in the middle of a sentence.

```ts title="sample.ts"
  return `Hello ${name}${excited ? '!' : '.'}`;
}
```

:::note
Switching fonts here only affects this page, and only until you reload it. Nothing is saved.
:::

## Setting your own

Three tokens decide the families, whatever the preset. Set them in a [`customCss`](/customization/theming/#add-a-stylesheet) file:

```css title="src/styles/fonts.css"
:root {
  --font-body: 'Inter', system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', monospace;
  --font-display: 'Playfair Display', serif;
}
```

| Token            | Used for                                                  |
| ---------------- | --------------------------------------------------------- |
| `--font-body`    | Body text, the interface and headings from `h3` down      |
| `--font-mono`    | Code blocks and inline code                               |
| `--font-display` | `h1` and `h2`, falling back to `--font-body` when unset   |

A token only names a family: the font itself still has to reach the browser. In an Astro project, declare it with the [Astro Fonts API](https://docs.astro.build/en/guides/fonts/) to have it self-hosted, load it from the `head` [slot](/customization/slots/), and point the token at its CSS variable:

<Steps>

### Declare the font

```js title="astro.config.mjs"

  fonts: [
    { provider: fontProviders.fontsource(), name: 'Inter', cssVariable: '--font-inter' },
  ],
  integrations: [
    zenith({
      title: 'My Docs',
      fonts: false,
      customCss: ['./src/styles/fonts.css'],
      slots: { head: './src/components/Fonts.astro' },
    }),
  ],
});
```

### Load it on every page

```astro title="src/components/Fonts.astro"
---
---

<Font cssVariable="--font-inter" preload />
```

### Use it

```css title="src/styles/fonts.css"
:root {
  --font-body: var(--font-inter);
}
```

</Steps>

With the [CLI](/cli/) there is no Astro configuration to declare fonts in: stick to a preset, to fonts installed on the reader's system, or to an `@font-face` rule of your own in the stylesheet.

`fonts: false` ships no font at all. Without tokens of your own, text then uses the system font stack.

## Sizes

Heading sizes are fluid: each level scales between a `-min` and a `-max` value, in pixels, with the width of the viewport. To make everything larger or smaller at once, change the two scales rather than each size:

```css
:root {
  --zd-heading-scale: 1.15; /* h1 to h6 */
  --zd-text-scale: 1.05; /* body text */
}
```

A single level can also be set on its own, in which case the scale no longer applies to it:

```css
:root {
  --h1-min: 32;
  --h1-max: 40;
}
```