#5253·unocss

preset-wind4: `font-*` utilities emit `var(--font-*)` without fallback — fonts silently break when the theme preflight is absent

Author: 61021Created Jul 23, 2026Updated Aug 27, 2026

Clear and concise description of the problem

As a developer using preset-wind4, font-sans / font-mono / font-serif compile to font-family: var(--font-sans) with no fallback, while the --font-* definitions are emitted separately by the on-demand theme preflight (:root, :host { --font-sans: ...; }). With default options this works fine. But any setup that suppresses preflights — preflights: { theme: false }, generate(code, { preflights: false }), or consuming split layers without the theme layer (e.g. bringing your own reset and only including the utilities layers) — produces declarations that are invalid at computed-value time, so the font silently falls back to the inherited one. No warning, no error — just a wrong font.

This is a regression-shaped footgun relative to preset-wind3, where .font-sans inlined the full family list and was safe under the same configurations. Verified on unocss 66.7.5 (and the behavior is present since wind4's introduction in 66.1.0).

Repro (66.7.5):

typescript
// uno.config.ts
import { defineConfig, presetWind4 } from 'unocss'

export default defineConfig({
  presets: [presetWind4({ preflights: { theme: false } })],
})
xml
<div class="font-sans">hello</div>

Output contains only:

css
.font-sans{font-family:var(--font-sans);}

--font-sans is defined nowhere → invalid at computed-value time → inherited font. wind3 output for the same class: .font-sans{font-family:ui-sans-serif,system-ui,...}.

I know theme: false is marked "Not recommended ⚠️" in the option types — the concern here is the silent failure mode, and layer-splitting setups hit the same breakage without ever touching that option.

Suggested solution

Emit the theme value as a var() fallback in the utility, the same way the wind4 reset already guards the default font (font-family: var(--default-font-family, ui-sans-serif, system-ui, ...)):

css
.font-sans{font-family:var(--font-sans, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", ...);}

Overriding via --font-sans keeps working identically; the fallback only kicks in when the var is absent. I'm happy to submit a PR for this if the direction is agreed.

Alternative

  • Document loudly (preset-wind4 docs + PreflightsTheme JSDoc) that the theme layer is load-bearing for font-* and other var-referencing utilities, and that dropping it silently breaks them.
  • Or emit a dev-time warning when a rule resolves a theme key to a CSS var while the theme preflight is disabled.

Additional context

Hit this in production: a project with its own reset/preflight setup shipped with every font-sans element silently rendering the browser default font.

Validations

  • Read the Contributing Guidelines.
  • Read the README.md of using the package.
  • Already used the Interactive Docs.
  • Check that there isn't already an issue that request the same feature to avoid creating a duplicate.