Custom Themes
OwnShip's three built-in themes — Light, Dark, and Sepia — cover most sites. For full color control, place a _theme.css file next to index.php. OwnShip loads it automatically after the built-in styles, no configuration needed.
How it works
_theme.css uses standard CSS to override any of OwnShip's color variables for any or all of the three themes. Be as sparse or as complete as you like — anything you don't override inherits from the built-in theme.
/* _theme.css — override only what you need */
[data-theme="light"] {
--heading: #1a3a6b;
--link: #1a3a6b;
}
The three selectors are [data-theme="light"], [data-theme="dark"], and [data-theme="sepia"].
Named themes — _theme-NAME.css
To add entirely new color schemes — or replace the built-in palette — create one or more named theme files alongside index.php. OwnShip discovers them on each page load and includes them in the theme cycle button. After dropping in a new file, reload the page for it to appear.
Prefer ready-made? Browse and download themes at ownship.cc/themes.
Name the file _theme-NAME.css where NAME becomes the theme's identifier. Inside, target [data-theme="NAME"] with a full set of color variables:
/* _theme-dracula.css */
[data-theme="dracula"] {
--bg: #282a36;
--bg-nav: #21222c;
--bg-code: #44475a;
--border: #44475a;
--text: #f8f8f2;
--text-muted: #6272a4;
--heading: #f8f8f2;
--link: #8be9fd;
--link-hover: #bd93f9;
--active-bg: #44475a;
--active: #bd93f9;
--head-bg: #21222c;
}
Set theme = dracula in _site.ini to make it the default starting theme.
Theme icon — --theme-icon
Optionally give a theme its own glyph for the theme button and the right-click theme menu by adding a --theme-icon declaration to the theme's block:
[data-theme="dracula"] {
--theme-icon: "🧛";
--bg: #282a36;
/* …the rest of the palette… */
}
The value is one grapheme — an emoji or a single letter, the designer's choice — and it is rendered verbatim. Note that many emoji are multiple code points (ZWJ sequences like 👨👩👧, flags like 🏳️🌈, skin-tone modifiers like 👍🏽); the whole value is used as-is and is never truncated to its first code point, so those render intact. If a theme omits --theme-icon, it falls back to the built-in glyph for stock names, otherwise a neutral ◐.
Adding to the built-in themes
Drop-in themes always extend the stock cycle — the three built-ins are always present unless you explicitly suppress them.
| Files present | Theme cycle |
|---|---|
| (none) | Light → Dark → Sepia |
_theme-dracula.css | Light → Dark → Sepia → Dracula |
_theme-dracula.css + _theme-nord.css | Light → Dark → Sepia → Dracula → Nord |
_theme-sepia.css (custom Sepia override) | Light → Dark → custom Sepia |
To suppress the built-in themes and show only your drop-ins, set show_stock_themes = false in _site.ini:
# _site.ini — custom themes only
show_stock_themes = false
theme = dracula
To selectively reenable an individual stock theme alongside your drop-ins, place an empty (or comment-only) stub file with the stock name. OwnShip will include it in the cycle and render it using the built-in styles — no CSS needed:
_theme-sepia.css ← empty file; sepia reappears in the cycle
_theme-dracula.css ← full custom theme
Button and safety behaviour
- N = 1: if only one theme is in the cycle, the theme button hides automatically — no configuration needed.
- Sparse files are safe: any variable you omit falls back to OwnShip's light theme defaults, so a half-finished theme file won't break the layout.
- Invalid
theme =: if_site.ininames a theme that isn't in the discovered cycle, OwnShip falls back to the first available theme.
Available variables
| Variable | Controls |
|---|---|
--bg | Page background |
--bg-nav | Nav pane background |
--bg-code | Code block background |
--border | Borders and dividers |
--text | Body text |
--text-muted | Secondary text |
--heading | Heading color (h1–h6) |
--link | Link color |
--link-hover | Link hover color |
--active-bg | Nav item highlight background |
--active | Nav active item text color |
--head-bg | Header and footer background |
Page-specific styles
OwnShip adds a data-page attribute to the <main> element with the current page's slug (filename without extension). Use it in _theme.css to style individual pages differently:
[data-page="index"] main h1 { font-size: 3rem; } /* bigger hero on home */
[data-page="contact"] main { background: var(--bg-nav); }
The home page always gets data-page="index". Nested pages include the full path: data-page="subfolder/page".
JavaScript theming — _theme.js
For effects that CSS alone can't achieve, place a _theme.js file next to _theme.css. OwnShip loads it automatically at the end of <body>, after all page content and OwnShip's own scripts:
// _theme.js — runs after the page is fully rendered
document.querySelectorAll('main h2').forEach(function(el) {
el.style.borderBottom = '2px solid var(--link)';
});
Use it for DOM manipulation, scroll effects, staggered animations, or anything else a stylesheet can't express. It has full access to the rendered page.
Notes
_theme.cssand_theme.jsapply to the root directory only.show_theme_buttonworks normally — readers can still cycle themes, and your overrides apply within whichever theme they choose._theme.cssis plain CSS — variable overrides are just the starting point.