---
title: "Recipes"
slug: theming-recipes
section: theming
order: 80
level: intermediate
description: "Common theming patterns: brand-color override without authoring a pack, page-level theme wrapper, dark-mode-only utility classes, and lazy-loaded pack switching."
---

# Recipes

Patterns that come up often enough to be worth canonicalizing.

## 1. Brand color override (no new pack)

You don't need to author a full pack just to recolor your accent. Override
the relevant tokens in your `input.css`:

```css
/* static/css/input.css */
:root {
    --primary: 280 85% 60%;          /* purple */
    --primary-foreground: 0 0% 100%;
    --ring: 280 85% 60%;
    --link: 280 85% 60%;
    --link-hover: 280 85% 70%;
}
```

This wins over the active pack because the cascade resolves your explicit
`:root` rule last. Switching packs still works for everything else (cards,
borders, surfaces, text) — they just won't override `--primary` while
your stylesheet is loaded.

**When to use**: you want one consistent brand color regardless of which
shipped pack the user picked.

## 2. Page-level theme wrapper

A different look on a single page (e.g. a marketing landing inside an
admin app):

```css
/* static/css/input.css */
.theme-marketing {
    --background: 40 30% 7%;
    --foreground: 40 20% 92%;
    --primary: 28 85% 55%;
    --primary-foreground: 30 25% 8%;
    --card: 40 20% 9%;
    --border: 0 0% 16%;
}
```

```django
{% extends "base.html" %}
{% block body %}
<body class="theme-marketing">
    {% block content %}...{% endblock %}
</body>
{% endblock %}
```

Tailwind utilities and djust components on that page will repaint to the
overridden tokens. The user-facing pack switcher still affects every
other page on the site.

**When to use**: a landing page with a designer-controlled palette
inside an otherwise theme-switchable app.

## 3. Per-section accent

Sometimes one section needs a different accent without changing the rest:

```css
/* Pricing card group with a green accent */
.pricing-grid {
    --primary: 160 60% 40%;
    --primary-foreground: 0 0% 100%;
}
```

```html
<section class="pricing-grid">
    <article class="pricing-card">
        <h3>Pro</h3>
        <button class="bg-brand-rust">Choose Pro</button>
        <!--                       ^ uses --primary, now green here -->
    </article>
</section>
```

The CSS-variable inheritance scope means the override applies to every
descendant.

## 4. Dark-mode-only styling without `@media (prefers-color-scheme)`

djust's mode switch flips a `.dark` class on `<html>` (or sets
`:root[data-theme="dark"]`, depending on pack config). Use it for any
truly mode-specific styling:

```css
.dark .my-card {
    background: hsl(var(--card));
    box-shadow: 0 4px 12px rgba(0 0 0 / 0.5);
}

:root:not(.dark) .my-card {
    background: hsl(var(--card));
    box-shadow: 0 4px 12px rgba(0 0 0 / 0.05);   /* softer in light */
}
```

This respects the user's session-persisted choice — `prefers-color-scheme`
would only respect the OS-level setting and would conflict with the
in-app switcher.

## 5. Component-scoped variable (no pack involvement)

For a component that needs a knob the pack doesn't model, declare the
variable on the component root:

```css
.toast {
    --toast-duration: 4s;
    --toast-max-width: 360px;
    animation: toast-fade var(--toast-duration);
    max-width: var(--toast-max-width);
}
```

To override per-instance, just inline:

```html
<div class="toast" style="--toast-duration: 8s">Long-running message</div>
```

No pack changes needed.

## 6. Honoring system theme on first visit

Default to the OS preference for first-time visitors, persist their
explicit choice afterward:

```python
# settings.py
LIVEVIEW_CONFIG = {
    'theme': {
        'pack': 'docs',
        'default_mode': 'dark',         # used when no session + no OS hint
        'enable_dark_mode': True,
        'persist_in_session': True,
        'respect_system_preference': True,   # opt-in, falls through if no
                                             # session value is set
    },
}
```

The user's first visit reads `prefers-color-scheme`; their first explicit
toggle of the mode switcher writes a session value that wins from then
on.

## 7. Showing the active pack in a debug strip

Useful in staging — drop a small badge in the corner so the QA team can
see which pack is rendering:

```django
{% if request.user.is_staff %}
    <div class="debug-strip">
        pack: {{ theme_pack }}
        · mode: {{ theme_resolved_mode }}
    </div>
{% endif %}
```

```css
.debug-strip {
    position: fixed; bottom: 8px; left: 8px;
    padding: 4px 8px; font-family: monospace; font-size: 11px;
    color: hsl(var(--muted-foreground));
    background: hsl(var(--card) / 0.9);
    border: 1px solid hsl(var(--border));
    border-radius: 4px;
    pointer-events: none; z-index: 9999;
}
```

## See also

- **[Authoring a pack](/theming/authoring-a-pack/)** — for the cases
  these recipes can't cover.
- **[`extra_css_vars`](/theming/extra-css-vars/)** — for project-specific
  knobs that should travel with the pack.
- **[Troubleshooting](/theming/troubleshooting/)** — when a recipe
  doesn't work.
