Custom Themes
Create custom themes with CSS variables
Last updated: March 15, 2026
Custom Themes
Create themes by defining CSS variables. No template editing required.
Theme Structure
themes/
├── common/ # Shared (don't modify)
│ ├── templates/
│ └── static/
│ ├── css/
│ └── js/
├── default/ # Default theme
│ └── static/css/main.css
└── my-theme/ # Your custom theme
└── static/css/main.css
Creating a Theme
1. Create Directory
mkdir -p themes/my-theme/static/css
2. Create main.css
/* themes/my-theme/static/css/main.css */
/* Light mode */
:root[data-theme="light"] {
--bg-primary: #ffffff;
--bg-secondary: #f8fafc;
--bg-tertiary: #f1f5f9;
--text-primary: #0f172a;
--text-secondary: #475569;
--text-tertiary: #94a3b8;
--text-muted: #cbd5e1;
--border-primary: #e2e8f0;
--border-secondary: #f1f5f9;
--accent-primary: #3b82f6;
--accent-hover: #2563eb;
--link-color: #2563eb;
--link-hover: #1d4ed8;
--bg-code: #f8fafc;
--bg-hover: #f1f5f9;
--shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
--shadow-md: 0 4px 6px rgba(0,0,0,0.1);
}
/* Dark mode */
:root[data-theme="dark"] {
--bg-primary: #0f172a;
--bg-secondary: #1e293b;
--bg-tertiary: #334155;
--text-primary: #f8fafc;
--text-secondary: #cbd5e1;
--text-tertiary: #94a3b8;
--text-muted: #64748b;
--border-primary: #334155;
--border-secondary: #1e293b;
--accent-primary: #60a5fa;
--accent-hover: #3b82f6;
--link-color: #60a5fa;
--link-hover: #93c5fd;
--bg-code: #1e293b;
--bg-hover: #334155;
--shadow-sm: 0 1px 2px rgba(0,0,0,0.3);
--shadow-md: 0 4px 6px rgba(0,0,0,0.5);
}
3. Use Your Theme
minimaldoc build --theme my-theme
Or in config:
theme: my-theme
CSS Variables Reference
Backgrounds
| Variable | Purpose |
|---|---|
--bg-primary |
Page background |
--bg-secondary |
Sidebar, cards |
--bg-tertiary |
Nested elements, highlights |
--bg-code |
Code block background |
--bg-hover |
Hover states |
Text
| Variable | Purpose |
|---|---|
--text-primary |
Main content |
--text-secondary |
Secondary text, descriptions |
--text-tertiary |
Muted text |
--text-muted |
Very subtle text |
Borders
| Variable | Purpose |
|---|---|
--border-primary |
Main borders |
--border-secondary |
Subtle borders |
Accents
| Variable | Purpose |
|---|---|
--accent-primary |
Buttons, active states |
--accent-hover |
Hover on accent elements |
--link-color |
Link text |
--link-hover |
Link hover |
Shadows
| Variable | Purpose |
|---|---|
--shadow-sm |
Subtle depth |
--shadow-md |
Cards, dropdowns |
Custom Fonts
Google Fonts
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
:root {
--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
}
body {
font-family: var(--font-sans);
}
Monospace Font
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap');
code, pre {
font-family: 'JetBrains Mono', 'Fira Code', monospace;
}
Self-Hosted Fonts
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.woff2') format('woff2');
font-weight: normal;
font-style: normal;
font-display: swap;
}
Theme Examples
Warm Theme
:root[data-theme="light"] {
--bg-primary: #fffbeb;
--bg-secondary: #fef3c7;
--text-primary: #78350f;
--accent-primary: #f59e0b;
--link-color: #d97706;
}
:root[data-theme="dark"] {
--bg-primary: #1c1917;
--bg-secondary: #292524;
--text-primary: #fef3c7;
--accent-primary: #fbbf24;
--link-color: #fcd34d;
}
Cool Theme
:root[data-theme="light"] {
--bg-primary: #f0f9ff;
--bg-secondary: #e0f2fe;
--text-primary: #0c4a6e;
--accent-primary: #0284c7;
--link-color: #0369a1;
}
:root[data-theme="dark"] {
--bg-primary: #0c1929;
--bg-secondary: #1e3a5f;
--text-primary: #e0f2fe;
--accent-primary: #38bdf8;
--link-color: #7dd3fc;
}
High Contrast
:root[data-theme="light"] {
--bg-primary: #ffffff;
--text-primary: #000000;
--accent-primary: #0000ff;
--border-primary: #000000;
}
:root[data-theme="dark"] {
--bg-primary: #000000;
--text-primary: #ffffff;
--accent-primary: #00ffff;
--border-primary: #ffffff;
}
Admonition Colors
Customize admonition appearance:
/* Info */
.admonition.info {
--admonition-bg: #dbeafe;
--admonition-border: #3b82f6;
--admonition-text: #1e40af;
}
[data-theme="dark"] .admonition.info {
--admonition-bg: rgba(59, 130, 246, 0.15);
--admonition-text: #93c5fd;
}
/* Warning */
.admonition.warning {
--admonition-bg: #fef3c7;
--admonition-border: #f59e0b;
--admonition-text: #92400e;
}
/* Danger */
.admonition.danger {
--admonition-bg: #fee2e2;
--admonition-border: #ef4444;
--admonition-text: #991b1b;
}
Code Block Colors
Override syntax highlighting:
/* Code block background */
pre {
background: var(--bg-code) !important;
}
/* Line numbers */
.chroma .ln {
color: var(--text-muted);
}
Testing Themes
Local Development
# Build with theme
minimaldoc build ./docs --theme my-theme --output dist
# Serve locally
python -m http.server -d dist 8080
Test Both Modes
Toggle dark mode in browser to verify both color schemes.
Checklist
- Light mode readable
- Dark mode readable
- Links visible
- Code blocks legible
- Admonitions distinct
- Hover states visible
- Borders appropriate
- Search input styled
Contributing Themes
To add a theme to MinimalDoc, open a PR on the GitHub repository.