Font Switcher — Vanilla

Font pair (sans + mono) switcher with vanilla HTML + JS. Live example and copyable markup.

Font Switcher

Font pair dropdown with preview and keyboard navigation. Same BEM structure and behavior as the Astro FontSwitcher: sets --font-family and --font-family-mono on <html>, persists in localStorage (key fontPair).

Add this component

The command below includes <strong>Font Switcher</strong>—run it in your project directory to install this component (and the CSS if needed). No prompts.

Choose your package manager — click a tab to select, then copy the command.

npm pnpm yarn bun

Live example

The switcher below is a working example (same Astro component so it runs on this page). In a vanilla-only project use the same HTML and the FontSwitcher script from the package or wire option clicks to set CSS variables and localStorage.fontPair.

Live Example

HTML (structure)

Copy the markup below. Ensure Rizzo CSS is loaded. The Astro FontSwitcher script initializes every [data-font-switcher]; or wire trigger/menu and option clicks yourself.

html html
<div class="font-switcher" data-font-switcher>
  <button type="button" class="font-switcher__trigger" aria-expanded="false" aria-haspopup="true" aria-controls="font-pair-menu" aria-label="Select font pair" id="font-pair-trigger">
    <span class="font-switcher__label" data-font-pair-label>Geist (Sans + Mono)</span>
    <svg class="font-switcher__icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>
  </button>
  <div class="font-switcher__menu" id="font-pair-menu" role="menu" aria-labelledby="font-pair-trigger" aria-label="Font pair selection" aria-orientation="vertical" aria-hidden="true" tabindex="-1">
    <div class="font-switcher__menu-options">
      <div class="font-switcher__option" role="menuitemradio" aria-checked="false" tabindex="-1" data-font-pair-value="geist" data-font-pair-sans="var(--font-family-geist-sans)" data-font-pair-mono="var(--font-family-geist-mono)" data-font-pair-label="Geist (Sans + Mono)">Geist (Sans + Mono)</div>
      <div class="font-switcher__option" role="menuitemradio" aria-checked="false" tabindex="-1" data-font-pair-value="inter-jetbrains" data-font-pair-sans="var(--font-family-inter)" data-font-pair-mono="var(--font-family-jetbrains-mono)" data-font-pair-label="Inter + JetBrains Mono">Inter + JetBrains Mono</div>
      <div class="font-switcher__option" role="menuitemradio" aria-checked="false" tabindex="-1" data-font-pair-value="ibm-plex" data-font-pair-sans="var(--font-family-ibm-plex-sans)" data-font-pair-mono="var(--font-family-ibm-plex-mono)" data-font-pair-label="IBM Plex Sans + Mono">IBM Plex Sans + Mono</div>
      <div class="font-switcher__option" role="menuitemradio" aria-checked="false" tabindex="-1" data-font-pair-value="source" data-font-pair-sans="var(--font-family-source-sans-3)" data-font-pair-mono="var(--font-family-source-code-pro)" data-font-pair-label="Source Sans 3 + Source Code Pro">Source Sans 3 + Source Code Pro</div>
      <div class="font-switcher__option" role="menuitemradio" aria-checked="false" tabindex="-1" data-font-pair-value="dm" data-font-pair-sans="var(--font-family-dm-sans)" data-font-pair-mono="var(--font-family-dm-mono)" data-font-pair-label="DM Sans + DM Mono">DM Sans + DM Mono</div>
      <div class="font-switcher__option" role="menuitemradio" aria-checked="false" tabindex="-1" data-font-pair-value="outfit-jetbrains" data-font-pair-sans="var(--font-family-outfit)" data-font-pair-mono="var(--font-family-jetbrains-mono)" data-font-pair-label="Outfit + JetBrains Mono">Outfit + JetBrains Mono</div>
    </div>
    <div class="font-switcher__preview" data-font-preview aria-hidden="true">
      <div class="font-switcher__preview-title">Preview</div>
      <div class="font-switcher__preview-sample" data-font-preview-sample>Aa Bb Cc 012</div>
      <div class="font-switcher__preview-mono" data-font-preview-mono>code</div>
    </div>
  </div>
</div>

View Font Switcher on the Astro docs for usage and keyboard behavior.

Other frameworks: Astro · Svelte · Vue · React

← Back to Vanilla components