# Font loading and substitution

Connect application or external fonts and separate logical families, rendered faces and export resources.

A name in the font toolbar does not mean the browser has that font. Missing fonts affect widths, wrapping and pagination. Choose explicit sources and distinguish saved font intent from what this device can render.

## Option one: application-mounted fonts

For a fixed brand font or offline deployment, declare an accessible `@font-face` in application CSS, wait for loading, then disclose its exact CSS family through `mountedFamilies`. `Application Serif` is an example name, not a bundled font; replace it with your actual face.

### classic/fonts/application.ts

```ts
import type { ClassicEditorWebFontOptions } from "@quirekit/classic-editor";

/**
 * Waits for an application-owned @font-face before creating Classic.
 * @param owner - Browser document whose stylesheet already declares the face.
 * @returns Explicit mounted-family configuration without an external catalog.
 */
export async function prepareApplicationFonts(owner: Document): Promise<ClassicEditorWebFontOptions> {
  const faces = await owner.fonts.load('16px "Application Serif"');
  if (faces.length === 0) throw new Error("Application Serif has no registered @font-face.");
  return { families: [], catalogs: [], mountedFamilies: [{ family: "Application Serif", displayName: "应用正文字体" }] };
}

```

```ts [Before creating Classic]
const webFonts = await prepareApplicationFonts(host.ownerDocument)
const instance = createClassicEditor({ element: host, preset, document, webFonts })
```

Use the host, Word preset and content from the [quick start](/en/classic/quick-start). `mountedFamilies` does not load CSS. `webFonts: false` neither loads missing fonts nor eliminates font differences.

`displayName` labels a family; it cannot replace its exact `family`. Configuring a source does not change content's font choice. Use installed `setFontFamily(family)` for the current selection. The document font theme belongs to canonical document configuration.

## Option two: install external fonts on demand

`webFonts` accepts `families`, `catalogs` and searchable `sources`. Families disclose installable metadata. Catalogs resolve exact family names into complete manifests; sources provide search, paging and manifest resolution. A manifest includes version, faces, assets and license information, rather than just a display name or stylesheet URL.

After mounting, read `instance.fontLibrary`. Subscribe to changes, then call `install(family)` after an explicit user action. Its Promise completes after browser registration and layout invalidation. `previewFamily()` previews without adding an imported-family record; `importFamily()` manages explicit import. Unsubscribe on exit/library replacement and recheck instance ownership after asynchronous work.

Supplying your own families/catalogs replaces the default configuration; do not assume default sources remain. Control resource budgets through `maxAssetBytes`, `maxConcurrentAssets`, `fetch` and `cache`.

## Understand font status

`instance.documentFontStatus` describes the document body font:

| Field or status | Meaning |
| --- | --- |
| `requestedFamily` | Logical family retained in content |
| `renderedFamily` | Selected concrete family, not a guarantee for every glyph |
| `pending` | Resolution or loading is in progress |
| `available` | Requested family is available |
| `substituted` | An explicit substitute is used while logical intent remains |
| `unresolved` | No concrete family has been confirmed |

Do not silently rewrite content's family when substituting. Scripts and individual missing glyphs can still use glyph fallback, so one body-font status does not establish identical rendering throughout the document.

## Verify layout and export

Built-in installation refreshes font metrics and layout. If your application loads CSS fonts after mounting, call the current `instance.editor?.view.refreshFontMetrics()` after readiness. Never refresh a discarded Core.

Cached assets, browser registration and exportable font bytes are different resources. `fontLibrary.getInstallations()` exposes completed installations. Local-only records contain no embeddable bytes, so browser availability does not guarantee embedded exports. Confirm resources and applicable rights for the selected export service.

Test first load, cache hits, offline behavior, failed downloads and mixed scripts. After readiness, inspect wrapping, page count and selection geometry, rather than only the font dropdown. See configuration types in the [instance reference](/en/classic/reference).
