---
title: "extra_css_vars"
slug: theming-extra-css-vars
section: theming
order: 50
level: intermediate
description: "Project-specific named knobs the standard token set doesn't model — gutter widths, accent variants, animation timings. Includes mode-specific overrides."
---

# `extra_css_vars`

The standard token set covers colors, typography, animation, and a few
geometric primitives. Anything else — project-specific gutter widths,
custom accent colors, animation timing constants, layout knobs — lives in
the `extra_css_vars` slots on `ThemePreset`.

## Three slots, one purpose

```python
ThemePreset(
    name='docs',
    light=LIGHT_TOKENS,
    dark=DARK_TOKENS,

    # Emitted in :root regardless of mode.
    extra_css_vars={
        '--docs-gutter': '32px',
        '--docs-section-num-color': 'var(--primary)',
        '--docs-pull-quote-bg': 'rgba(255 255 255 / 0.03)',
    },

    # Mode-specific overrides. If omitted, extra_css_vars is used for
    # both modes. Useful for surface colors that differ between light
    # and dark.
    extra_css_vars_light={
        '--docs-paper': '#fafaf7',
        '--docs-shadow': 'rgba(0 0 0 / 0.1)',
    },
    extra_css_vars_dark={
        '--docs-paper': '#11100d',
        '--docs-shadow': 'rgba(0 0 0 / 0.5)',
    },
)
```

## When to use which slot

| Slot | When to use |
|---|---|
| `extra_css_vars` | Variables whose value is the same in light and dark mode (gutter widths, animation durations, layout knobs that aren't color-coupled). |
| `extra_css_vars_light` | Light-mode-specific values (paper color, soft shadow, light noise texture). |
| `extra_css_vars_dark` | Dark-mode-specific values (deep ink, harder shadow, dark noise texture). |

You can use all three together: a base `extra_css_vars` for shared
constants, then mode-specific overrides for the values that *do* differ
between modes.

## Consuming in CSS

Reference your custom variables anywhere in your stylesheet:

```css
.docs-section {
    padding: 48px var(--docs-gutter);
    border-bottom: 1px solid var(--color-brand-border);
}

.docs-section__num {
    color: var(--docs-section-num-color);
}

.docs-paper {
    background: var(--docs-paper);
    box-shadow: 0 4px 12px var(--docs-shadow);
}
```

Mode swaps repaint these the same way they repaint the standard tokens —
no JavaScript needed.

## Naming conventions

Two conventions cover most cases:

- **Prefix with your project name** for site-wide knobs:
  `--docs-gutter`, `--docs-paper`, `--marketing-hero-height`.
- **Prefix with your component name** for component-scoped knobs:
  `--card-padding`, `--combobox-max-height`, `--toast-duration`.

The standard `--background` / `--primary` / `--border` namespace is
reserved for djust's shadcn-style tokens — don't redeclare those in
`extra_css_vars`. If you need to override `--primary` for a specific page
or section, use the [Recipes](/theming/recipes/) patterns.

## Don't put structural CSS here

`extra_css_vars` is for *named knobs*, not for CSS rules or selectors.
Putting structural rules in a theme pack means every other pack on your
site needs to redefine them — see
[Structure vs. style](/theming/structure-vs-style/) for the failure mode
and the right alternative.

## A real example

The docs.djust.org house theme uses `extra_css_vars` for one knob:

```python
# djust/python/djust/theming/themes/docs.py
PRESET = ThemePreset(
    name='docs',
    display_name='docs.djust.org',
    light=LIGHT,
    dark=DARK,
    default_mode='dark',
    extra_css_vars={
        '--docs-gutter': '32px',
    },
)
```

That single knob is consumed by every editorial section in
`static/css/input.css` (`.docs-hero`, `.docs-features`, `.docs-section`,
etc.). If the editorial layout ever needed wider or narrower gutters per
pack, we'd just override the value in a different pack's
`extra_css_vars` — no CSS changes.

## See also

- **[Authoring a pack](/theming/authoring-a-pack/)** — where
  `extra_css_vars` lives in the full pack definition.
- **[Structure vs. style](/theming/structure-vs-style/)** — what does NOT
  belong in `extra_css_vars` (or anywhere in a pack).
- **[Tokens](/theming/tokens/)** — the standard token set you're
  *extending*, not replacing.
