Theming
DocAnvil's appearance is customizable through three layers, each building on the last:
- CSS variable overrides in
docanvil.toml— quick color and font changes - Custom CSS file — full control over any element
- Template overrides — replace the entire HTML layout with Tera templates
CSS Variables in Config
The simplest way to customize the theme. Add variables under [theme.variables] in docanvil.toml:
[theme.variables]
color-primary = "#059669"
color-primary-light = "#34d399"
color-link = "#059669"
color-link-hover = "#047857"
These are injected as a :root style block after the default theme, overriding the built-in values. Variable names omit the -- prefix — DocAnvil adds it automatically.
Custom CSS File
For more control, point custom_css to a stylesheet:
[theme]
custom_css = "theme/custom.css"
This file loads after both the default theme and config variable overrides, so it has the highest CSS specificity. Use it for:
- Additional variable overrides in a
:rootblock - Custom selectors targeting specific elements
- New styles for your own classes (via inline attributes)
Common Customizations
# docanvil.toml — change accent color and font
[theme.variables]
color-primary = "#059669"
color-primary-light = "#34d399"
color-link = "#059669"
font-body = "Georgia, serif"/* theme/custom.css — wider content area with dark code blocks */
.content {
max-width: 960px;
}
.content pre {
background: #1e293b;
color: #e2e8f0;
border-color: #334155;
}
.content pre code {
color: inherit;
}
Load Order
Styles are applied in this order (last wins):
- Default theme (
style.cssembedded in the binary) - Config variables (
[theme.variables]→:root { ... }) - Custom CSS file (
custom_csspath)
Specificity
If a custom CSS rule doesn't seem to take effect, check that your selector is specific enough to override the default theme. Using .content pre is more specific than just pre.
Template Overrides
For complete control over the HTML structure, override the default Tera template. Create a file at theme/templates/layout.html in your project:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{ page_title }} — {{ project_name }}</title>
<style>{{ default_css | safe }}</style>
{% if css_overrides %}
<style>:root { {{ css_overrides }} }</style>
{% endif %}
{% if custom_css_path %}
<link rel="stylesheet" href="/{{ custom_css_path }}">
{% endif %}
{% block head %}{% endblock %}
</head>
<body>
{% block sidebar %}
<nav class="sidebar">
<div class="project-name">{{ project_name }}</div>
{{ nav_html | safe }}
</nav>
{% endblock %}
<main class="content">
{% block content %}
{{ content | safe }}
{% endblock %}
{% block footer %}
<div class="footer">
Built with <a href="https://github.com/docanvil/docanvil">DocAnvil</a>
</div>
{% endblock %}
</main>
{% block scripts %}{% endblock %}
</body>
</html>
Template Blocks
| Block | Purpose |
|---|---|
head |
Extra <head> content (fonts, meta tags, analytics) |
sidebar |
The navigation sidebar |
content |
Main page content area |
footer |
Footer below content |
scripts |
JavaScript at end of body |
Template Variables
| Variable | Type | Description |
|---|---|---|
page_title |
String | Title of the current page |
project_name |
String | Project name from docanvil.toml |
default_css |
String | The full default stylesheet (use with safe filter) |
css_overrides |
String | CSS variable overrides from config |
custom_css_path |
String | Path to custom CSS file, if configured |
nav_html |
String | Rendered navigation HTML (use with safe filter) |
content |
String | Rendered page HTML (use with safe filter) |
live_reload |
Boolean | Whether the dev server is running |
Note
The default template includes JavaScript for tab switching, sidebar collapse/expand, navigation filtering, and popover positioning. If you override the scripts block, you'll need to re-implement any of these features you want to keep.
Related Pages
- CSS Variables — complete list of every variable and its default value
- Configuration —
docanvil.tomlandnav.tomlreference