Themes

How the light and dark themes color everything — the page, highlighted code, diagrams and widgets — from one set of tokens, how a reader switches between them, and how far a page can change the look. It is a task and reference article under the viewer.

The tokens

The viewer has a light and a dark theme. Which one shows is the one the reader switched to with the theme switch, or — until they switch, and on a page without one — the system setting (prefers-color-scheme). The chosen theme is set on the page as data-theme="light" or data-theme="dark" on <html>, before it paints, and every dark value hangs off that. The page's colors come from seven tokens, defined in assets/style.css:

Token Used for Light Dark
--background page background #ffffff #000000
--surface sidebar, quotes #f5f5f7 #1d1d1f
--text body text #1d1d1f #f5f5f7
--muted secondary text, group headings #6e6e73 #a1a1a6
--border rules, borders, hover #d2d2d7 #424245
--accent links, the current sidebar entry #0066cc #2997ff
--code code background #f5f5f7 #1d1d1f

Seven more tokens color highlighted code. Their values are Xcode's default light and dark palettes:

Token Light Dark
--syntax-keyword #9b2393 #ff7ab2
--syntax-string #c41a16 #ff8170
--syntax-number #1c00cf #d9c97c
--syntax-comment #5d6c79 #7f8c98
--syntax-type #0b4f79 #dabaff
--syntax-function #326d74 #67b7a4
--syntax-attribute #815f03 #fd8f3f

Two font tokens, --font and --font-mono, are shared by both themes. A theme is a set of values for these tokens. A few colors are fixed rather than taken from a token: the text of the current sidebar entry (white); the red (#d70015) of diagram errors, comment errors, the problems bar and broken-link marks. How the tokens reach highlighted code and diagrams is on How themes reach code and diagrams.

Choosing a theme

Every page — a site's, a doc, a deck — has a theme switch in its top-right corner: one small icon button that switches between light and dark. It shows the theme a click switches to — a moon in light, a sun in dark. Until the reader clicks it, the page follows their system setting; after, the browser remembers the theme they switched to, for the address it was made on. A switch changes everything drawn from the tokens at once: the page, highlighted code, diagrams and widgets. On a site with a navbar the button sits at the right end of the bar. It is never printed, and a deck hides it in fullscreen. A document file turns it off with theme-selector: false; the page then follows the system setting, as before the switch existed.

Changing the look

The themes can't be changed per document. A document file has no theme field — any field its kind doesn't have stops devpage with an error — and the stylesheet is compiled into the binary, so there is no custom stylesheet option and no way to add a third theme without changing assets/style.css and rebuilding devpage.

What a page can do is carry its own CSS. Raw HTML passes through, so a <style> block in a page's Markdown is part of that page:

<style>
:root { --accent: #c00000; }
</style>

It applies while that page is shown — to the whole frame, the sidebar included, since a <style> element isn't scoped to the article — and to no other page: opening another page, by a link or a fresh load, replaces the page content and the <style> with it. A token set this way, as above, recolors everything that uses it, in both themes, because the rule comes after the built-in stylesheet; scope it to :root[data-theme="dark"] (or "light") to change one theme only — a @media (prefers-color-scheme: …) rule would follow the system, not the reader's choice. Nothing checks such CSS, and it rides along with the page's content, so use it for one page's needs rather than as a theme.

Topics