Skip to content
md-book

Theming#

md-book’s public theming API is a set of namespaced CSS custom properties. A theme is a single .css file that redefines them — load it after style.css:

<link rel="stylesheet" href="@ibitsuki0296/md-book/style.css" />
<link rel="stylesheet" href="/my-theme.css" />

The token contract#

:root {
  /* colour */
  --md-book-color-bg: #ffffff;
  --md-book-color-fg: #18181c;
  --md-book-color-fg-muted: #6f6f7b;
  --md-book-color-surface: #fafafa;
  --md-book-color-border: #e7e7ea;
  --md-book-color-accent: #4f46e5;
  --md-book-color-accent-fg: #ffffff;
  --md-book-color-code-bg: #fafafa;

  /* syntax highlighting */
  --md-book-color-tok-keyword: #7c3aed;
  --md-book-color-tok-string: #047857;
  --md-book-color-tok-function: #2563eb;

  /* typography */
  --md-book-font-body: "Inter", ui-sans-serif, system-ui, sans-serif;
  --md-book-font-mono: "JetBrains Mono", ui-monospace, Menlo, monospace;
  --md-book-leading: 1.7;

  /* layout */
  --md-book-measure: 46rem;       /* reading width   */
  --md-book-sidebar-width: 16rem;
  --md-book-toc-width: 14rem;
  --md-book-radius: 0.75rem;
}

themes/default.css in the package lists every token with its default value — copy it as a starting point. The primitive palette (--md-book-gray-*, --md-book-brand-*) is also overridable if you want to recolour in one place.

Fonts#

md-book never downloads fonts itself. The default stacks list Inter and JetBrains Mono first, so loading them (a <link> to Google Fonts, or self-hosted @font-face) is enough; without them the platform UI font is used.

Syntax highlighting#

Fenced code in js/ts, json, css, html, bash, yaml, python and diff is highlighted at render time by a tiny built-in tokenizer, coloured with the --md-book-color-tok-* tokens. Other languages stay plain. For full-grammar highlighting pass highlight: (code, lang) => html to mount() (Shiki, highlight.js, …), or set highlight: false on renderMarkdown() to switch the built-in one off.

Dark mode#

Provide a [data-theme="dark"] block. The runtime sets data-theme on <html>; with no theme file, dark is also applied from prefers-color-scheme.

:root[data-theme="dark"] {
  --md-book-color-bg: #0a0a0d;
  --md-book-color-fg: #f4f4f5;
  --md-book-color-border: #26262d;
  --md-book-color-accent: #818cf8;
}

Paste themeInitScript() (or the equivalent inline snippet) into <head> so the stored theme is applied before first paint.

Structural overrides#

The bundled rules live in @layer md-book.tokens, .base, .layout, .content, .components. Any rule you add without a layer wins over all of them, so you can restructure without specificity hacks:

.md-book-header { position: static; }   /* beats the layered `position: sticky` */

Don’t hard-code colours in structural overrides — go through a token so light and dark stay in sync. npm run validate:tokens enforces this on the bundled styles.