> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/kapishdima/fonttrio/llms.txt
> Use this file to discover all available pages before exploring further.

# CSS Variables

> Learn how Fonttrio uses CSS variables for flexible and customizable typography

# CSS Variables

Fonttrio uses CSS custom properties (CSS variables) to provide a flexible, maintainable system for applying font pairings to your project. This approach makes it easy to swap fonts, customize scales, and maintain consistency across your entire application.

## Why CSS Variables?

CSS variables offer several advantages for managing typography:

* **Single source of truth**: Define fonts once, use everywhere
* **Easy theming**: Switch entire pairings by changing a few variables
* **Dynamic updates**: Change typography at runtime without recompiling
* **Scoped customization**: Override variables for specific components
* **Framework agnostic**: Works with any CSS-based framework

## Core Font Variables

Every Fonttrio pairing defines three core CSS variables for the font families:

```css theme={null}
:root {
  --font-heading: var(--font-playfair-display);
  --font-body: var(--font-source-serif-4);
  --font-mono: var(--font-jetbrains-mono);
}
```

These three variables are then referenced throughout your stylesheets to apply the fonts consistently.

## Variable Structure in Pairings

Each pairing in the Fonttrio registry defines its CSS variables in the `cssVars` section:

<CodeGroup>
  ```json Editorial Pairing theme={null}
  {
    "name": "pairing-editorial",
    "cssVars": {
      "theme": {
        "--font-heading": "var(--font-playfair-display)",
        "--font-body": "var(--font-source-serif-4)",
        "--font-mono": "var(--font-jetbrains-mono)"
      }
    },
    "css": {
      "h1": { 
        "font-family": "var(--font-heading)", 
        "font-size": "2.25rem", 
        "line-height": "1.2", 
        "letter-spacing": "-0.025em", 
        "font-weight": "700" 
      },
      "h2": { 
        "font-family": "var(--font-heading)", 
        "font-size": "1.875rem", 
        "line-height": "1.25", 
        "letter-spacing": "-0.02em", 
        "font-weight": "600" 
      },
      "h3": { 
        "font-family": "var(--font-heading)", 
        "font-size": "1.5rem", 
        "line-height": "1.3", 
        "letter-spacing": "-0.015em", 
        "font-weight": "600" 
      },
      "h4, h5, h6": { 
        "font-family": "var(--font-heading)", 
        "letter-spacing": "-0.01em" 
      },
      "body, p": { 
        "font-family": "var(--font-body)", 
        "line-height": "1.65" 
      },
      "code, pre": { 
        "font-family": "var(--font-mono)" 
      }
    }
  }
  ```

  ```json Minimal Pairing theme={null}
  {
    "name": "pairing-minimal",
    "cssVars": {
      "theme": {
        "--font-heading": "var(--font-geist)",
        "--font-body": "var(--font-geist)",
        "--font-mono": "var(--font-geist-mono)"
      }
    },
    "css": {
      "h1": { 
        "font-family": "var(--font-heading)", 
        "font-size": "2.25rem", 
        "line-height": "1.15", 
        "letter-spacing": "-0.025em", 
        "font-weight": "700" 
      },
      "h2": { 
        "font-family": "var(--font-heading)", 
        "font-size": "1.875rem", 
        "line-height": "1.2", 
        "letter-spacing": "-0.02em", 
        "font-weight": "600" 
      },
      "h3": { 
        "font-family": "var(--font-heading)", 
        "font-size": "1.5rem", 
        "line-height": "1.3", 
        "letter-spacing": "-0.015em", 
        "font-weight": "500" 
      },
      "h4, h5, h6": { 
        "font-family": "var(--font-heading)", 
        "letter-spacing": "-0.01em" 
      },
      "body, p": { 
        "font-family": "var(--font-body)", 
        "line-height": "1.6" 
      },
      "code, pre": { 
        "font-family": "var(--font-mono)" 
      }
    }
  }
  ```
</CodeGroup>

## How Variables are Applied

Fonttrio uses a two-layer variable system for maximum flexibility:

### Layer 1: Font Family Variables

Individual fonts define their own CSS variable:

```css theme={null}
/* Each font gets its own variable */
--font-playfair-display: 'Playfair Display', serif;
--font-source-serif-4: 'Source Serif 4', serif;
--font-jetbrains-mono: 'JetBrains Mono', monospace;
```

### Layer 2: Semantic Variables

Pairings reference these font variables through semantic names:

```css theme={null}
/* Pairing maps semantic names to specific fonts */
--font-heading: var(--font-playfair-display);
--font-body: var(--font-source-serif-4);
--font-mono: var(--font-jetbrains-mono);
```

This two-layer approach means you can:

* Switch pairings by changing only 3 variables
* Override specific fonts while keeping others
* Create variations of existing pairings

## Using Variables in Your CSS

Once a pairing is installed, use the semantic variables in your stylesheets:

```css theme={null}
/* Headings use the heading font */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading);
}

/* Body text uses the body font */
body, p, li, td {
  font-family: var(--font-body);
}

/* Code uses the monospace font */
code, pre, kbd, samp {
  font-family: var(--font-mono);
}
```

## Fonttrio's Global CSS Setup

Here's how Fonttrio sets up its own CSS variable system in `/home/daytona/workspace/source/app/globals.css:85-98`:

```css app/globals.css theme={null}
@theme inline {
  --color-bg: var(--bg);
  --color-text: var(--text);
  --color-text-muted: var(--text-muted);
  --color-text-subtle: var(--text-subtle);
  --color-surface-border: var(--surface-border);
  --color-surface-border-strong: var(--surface-border-strong);
  --color-surface: var(--surface);
  --color-surface-hover: color-mix(in oklch, var(--surface) 80%, var(--foreground) 20%);

  --font-display: var(--font-bebas-neue), system-ui, sans-serif;
  --font-sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}
```

This shows how Fonttrio extends CSS variables beyond just fonts to include colors and other design tokens.

## Typography-Specific Variables

Beyond font families, you can create variables for the entire typography scale:

```css theme={null}
:root {
  /* Font families */
  --font-heading: var(--font-playfair-display);
  --font-body: var(--font-source-serif-4);
  --font-mono: var(--font-jetbrains-mono);
  
  /* Typography scale */
  --font-size-h1: 2.25rem;
  --font-size-h2: 1.875rem;
  --font-size-h3: 1.5rem;
  --font-size-body: 1rem;
  
  /* Line heights */
  --line-height-heading: 1.2;
  --line-height-body: 1.65;
  
  /* Letter spacing */
  --letter-spacing-tight: -0.025em;
  --letter-spacing-normal: 0em;
}

h1 {
  font-family: var(--font-heading);
  font-size: var(--font-size-h1);
  line-height: var(--line-height-heading);
  letter-spacing: var(--letter-spacing-tight);
}
```

## Scoped Customization

CSS variables can be scoped to specific elements or components:

```css theme={null}
/* Global default */
:root {
  --font-heading: var(--font-inter);
  --font-body: var(--font-inter);
}

/* Override for marketing section */
.marketing-hero {
  --font-heading: var(--font-playfair-display);
}

/* Override for documentation */
.docs-content {
  --font-body: var(--font-source-serif-4);
  --line-height-body: 1.75; /* More readable for long-form */
}

/* Both h1 elements use var(--font-heading) but get different fonts */
h1 {
  font-family: var(--font-heading);
}
```

<Note>
  Scoped variables allow you to use different pairings in different parts of your site without conflicts.
</Note>

## Dark Mode Support

CSS variables make theme switching trivial. Here's how Fonttrio handles dark mode in `/home/daytona/workspace/source/app/globals.css:7-50`:

```css app/globals.css theme={null}
:root {
  --bg: #fafafa;
  --text: #0a0a0a;
  --text-muted: #666666;
  --surface-border: #eaeaea;
  /* ...more light mode colors */
}

.dark {
  --bg: #0a0a0a;
  --text: #ededed;
  --text-muted: #888888;
  --surface-border: #1f1f1f;
  /* ...more dark mode colors */
}
```

The variables automatically update when the `.dark` class is applied, without touching font definitions.

## Dynamic Updates with JavaScript

You can change CSS variables programmatically:

```typescript theme={null}
// Switch to a different pairing at runtime
function switchPairing(pairing: 'editorial' | 'minimal' | 'brutalist') {
  const root = document.documentElement;
  
  if (pairing === 'editorial') {
    root.style.setProperty('--font-heading', 'var(--font-playfair-display)');
    root.style.setProperty('--font-body', 'var(--font-source-serif-4)');
    root.style.setProperty('--font-mono', 'var(--font-jetbrains-mono)');
  } else if (pairing === 'minimal') {
    root.style.setProperty('--font-heading', 'var(--font-geist)');
    root.style.setProperty('--font-body', 'var(--font-geist)');
    root.style.setProperty('--font-mono', 'var(--font-geist-mono)');
  }
  // Changes apply instantly across the entire site
}

// Adjust font size dynamically
function setFontSize(scale: number) {
  document.documentElement.style.setProperty('--font-size-body', `${scale}rem`);
}
```

## Fallback Fonts

Always provide fallback fonts for better loading experience:

```css theme={null}
:root {
  /* Fonttrio fonts with system fallbacks */
  --font-heading: var(--font-playfair-display), Georgia, serif;
  --font-body: var(--font-source-serif-4), Georgia, serif;
  --font-mono: var(--font-jetbrains-mono), 'Courier New', monospace;
  
  /* Fonttrio uses system fallbacks */
  --font-sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}
```

## Tailwind CSS Integration

If you're using Tailwind, extend your config to use CSS variables:

```javascript tailwind.config.js theme={null}
module.exports = {
  theme: {
    extend: {
      fontFamily: {
        heading: ['var(--font-heading)'],
        body: ['var(--font-body)'],
        mono: ['var(--font-mono)'],
      },
    },
  },
}
```

Then use in your HTML:

```html theme={null}
<h1 class="font-heading text-4xl">Heading</h1>
<p class="font-body text-base">Body text</p>
<code class="font-mono">Code</code>
```

## Next.js Font Integration

Fonttrio works seamlessly with Next.js font optimization:

```typescript app/layout.tsx theme={null}
import { Playfair_Display, Source_Serif_4, JetBrains_Mono } from 'next/font/google';

const playfair = Playfair_Display({
  subsets: ['latin'],
  variable: '--font-playfair-display',
  display: 'swap',
});

const sourceSerif = Source_Serif_4({
  subsets: ['latin'],
  variable: '--font-source-serif-4',
  display: 'swap',
});

const jetbrainsMono = JetBrains_Mono({
  subsets: ['latin'],
  variable: '--font-jetbrains-mono',
  display: 'swap',
});

export default function RootLayout({ children }) {
  return (
    <html className={`${playfair.variable} ${sourceSerif.variable} ${jetbrainsMono.variable}`}>
      <body>{children}</body>
    </html>
  );
}
```

## Variable Naming Conventions

Fonttrio follows these naming conventions:

```css theme={null}
/* ✅ Good: Semantic, purpose-driven names */
--font-heading
--font-body
--font-mono

/* ❌ Avoid: Font-specific names */
--font-playfair
--font-source

/* ✅ Good: Scale-specific variables */
--font-size-h1
--line-height-body
--letter-spacing-tight

/* ❌ Avoid: Non-descriptive names */
--size-1
--lh-a
--ls-small
```

## Best Practices

<Note>
  **Use Semantic Names**: Prefer `--font-heading` over `--font-playfair` so you can swap fonts without changing references.
</Note>

<Note>
  **Layer Your Variables**: Create base variables for individual fonts, then semantic variables that reference them.
</Note>

<Note>
  **Provide Fallbacks**: Always include fallback fonts in case custom fonts fail to load.
</Note>

<Note>
  **Scope Strategically**: Use scoped variables for component-level customization without affecting global styles.
</Note>

<Note>
  **Test Everywhere**: CSS variables work in all modern browsers, but test your fallbacks in older environments.
</Note>

## Common Patterns

### Pattern 1: Pairing Switcher

```css theme={null}
/* Define multiple pairings */
.pairing-editorial {
  --font-heading: var(--font-playfair-display);
  --font-body: var(--font-source-serif-4);
}

.pairing-minimal {
  --font-heading: var(--font-geist);
  --font-body: var(--font-geist);
}

/* Apply to body or root element */
body {
  font-family: var(--font-body);
}
```

### Pattern 2: Responsive Typography

```css theme={null}
:root {
  --font-size-h1: 2rem;
}

@media (min-width: 768px) {
  :root {
    --font-size-h1: 2.5rem;
  }
}

h1 {
  font-size: var(--font-size-h1);
}
```

### Pattern 3: User Preferences

```css theme={null}
/* Default */
:root {
  --font-size-base: 1rem;
}

/* User selected large text */
body.text-large {
  --font-size-base: 1.25rem;
}

/* All sizes scale proportionally */
body {
  font-size: var(--font-size-base);
}
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Font Pairings" href="/concepts/font-pairings" icon="layer-group">
    Learn about Fonttrio's pairing structure
  </Card>

  <Card title="Typography Scale" href="/concepts/typography-scale" icon="ruler">
    Understand how typography scales work
  </Card>

  <Card title="Installation" href="/installation" icon="download">
    Install Fonttrio and start using CSS variables
  </Card>

  <Card title="Customization" href="/guides/customizing-typography" icon="sliders">
    Customize pairings for your project
  </Card>
</CardGroup>
