OwnShip Guide

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 presentTheme cycle
(none)Light → Dark → Sepia
_theme-dracula.cssLight → Dark → Sepia → Dracula
_theme-dracula.css + _theme-nord.cssLight → 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

Available variables

VariableControls
--bgPage background
--bg-navNav pane background
--bg-codeCode block background
--borderBorders and dividers
--textBody text
--text-mutedSecondary text
--headingHeading color (h1–h6)
--linkLink color
--link-hoverLink hover color
--active-bgNav item highlight background
--activeNav active item text color
--head-bgHeader 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