Theming
Every value is a CSS custom property. Re-skin without forking.
Everything the default theme paints is a --blasdoc-* custom property. CSS,
SCSS or Tailwind can re-skin it without forking anything.
Applying the content styles
<main blasdocContentStyles>
<router-outlet />
</main>That one directive brings the typography, lists, tables, blockquotes and links. Without it you get Blasdoc's structure and none of its opinions, which is a legitimate choice.
Overriding a token
:root {
--blasdoc-code-radius: 0;
--blasdoc-code-bg: #0d1117;
--blasdoc-content-accent: oklch(0.62 0.19 264);
--blasdoc-table-head-bg: #161b22;
}The tokens
| Group | Examples |
|---|---|
| Content | --blasdoc-content-fg, --blasdoc-content-muted, --blasdoc-content-accent, --blasdoc-content-border, --blasdoc-content-line-height, --blasdoc-content-h1-size |
| Tables | --blasdoc-table-border, --blasdoc-table-head-fg, --blasdoc-table-hover, --blasdoc-table-radius, --blasdoc-table-padding, --blasdoc-table-font-size, --blasdoc-table-code-bg — plus --blasdoc-table-head-bg and --blasdoc-table-stripe, both transparent by default |
| Code | --blasdoc-code-bg, --blasdoc-code-fg, --blasdoc-code-radius, --blasdoc-code-padding, --blasdoc-code-panel-border |
| Code header | --blasdoc-toolbar-bg, --blasdoc-toolbar-fg, --blasdoc-toolbar-border, --blasdoc-toolbar-padding, --blasdoc-code-icon-bg, --blasdoc-code-icon-fg |
| Tabs | --blasdoc-tab-fg, --blasdoc-tab-fg-active, --blasdoc-tab-bg-active, --blasdoc-tab-border-active, --blasdoc-tab-radius, --blasdoc-tab-height, --blasdoc-tab-padding |
| Line numbers | --blasdoc-code-line-number-fg, --blasdoc-code-line-number-width, --blasdoc-code-line-number-gap |
| Preview | --blasdoc-preview-padding, --blasdoc-preview-bg, --blasdoc-preview-border, --blasdoc-preview-radius, --blasdoc-preview-min-height |
| Steps | --blasdoc-step-marker-bg, --blasdoc-step-marker-fg, --blasdoc-step-marker-size, --blasdoc-step-line, --blasdoc-step-gap, --blasdoc-step-ring, --blasdoc-step-ring-width |
| Badges | --blasdoc-badge-bg, --blasdoc-badge-fg, and -accent, -success, -warning, -danger pairs |
| Callouts | --blasdoc-callout-accent, --blasdoc-callout-bg, --blasdoc-callout-border, --blasdoc-callout-radius, --blasdoc-callout-padding, --blasdoc-callout-gap, --blasdoc-callout-title-size, --blasdoc-callout-icon-size — each redeclared per [data-type] |
| Focus | --blasdoc-focus, --blasdoc-focus-width |
| Type | --blasdoc-font, --blasdoc-mono |
Typography
Prose is set in --blasdoc-font, which is inherit: rendered Markdown takes
the type of the page it sits in, so Blasdoc never overrides a host
application's typeface. Code is different — a code block has to be monospaced,
so --blasdoc-mono names a stack. It leads with Geist Mono, Blasdoc's own
type, and falls through to the platform monospace stack when the project does
not ship it.
:root {
--blasdoc-font: 'Inter Variable', system-ui, sans-serif;
--blasdoc-mono: 'JetBrains Mono', ui-monospace, monospace;
}Blasdoc ships no font files and loads none: naming a family is all a theme
does. This site self-hosts Geist and Geist Mono through
@fontsource-variable/geist, which is the approach we recommend — no
third-party request on a prerendered page.
Dark mode
Two ways, both supported at once: prefers-color-scheme for visitors who never
touch a switch, and [data-theme] for applications that own the choice.
<html data-theme="dark">Setting data-theme wins over the media query, which is what a theme toggle
needs.
data-theme is not reserved to the root: any element may carry it, and the
scheme applies to that subtree alone. That is how a page shows one scheme
inside the other — the theme studio previews a dark
theme on a light page this way.
<div data-theme="dark">
<!-- dark, whatever the page around it is -->
</div>With Tailwind
The tokens are plain custom properties, so Tailwind's own values drop straight in:
:root {
--blasdoc-code-bg: var(--color-zinc-900);
--blasdoc-content-accent: var(--color-indigo-400);
}Replacing the UI entirely
Skip provideBlasdocTheme() and register your own components, or replace one at
a time — see Built-in components and
Headless directives.