Themes and colors
NgDoc styles every part of the site with CSS variables. A theme is a set of values for these variables, chosen by the data-theme attribute of the <html> element. NgDoc ships a light, a dark and an auto theme, and you can change any variable or add your own theme.
Themes
| Theme | data-theme | Colors |
|---|---|---|
| Light | (none) | The default values. |
| Dark | dark | The dark values. |
| Auto | auto | Light or dark, following the reader's system preference. |
The light theme is part of the NgDoc styles. The dark and auto themes are in a separate stylesheet: add it after the NgDoc styles in the build target.
{
"projects": {
"<project-name>": {
"architect": {
"build": {
"options": {
"styles": ["node_modules/@ng-doc/app/styles/global.css", "node_modules/@ng-doc/app/styles/themes/dark.css", "src/styles.css"]
}
}
}
}
}
}Readers switch the theme with , which cycles through Auto, Light and Dark (T key, which switches between light and dark (
Theme by default
Without a data-theme attribute, the site starts in the light theme. To start in another theme, set the attribute in index.html:
<!doctype html>
<html lang="en" data-theme="auto">
<head></head>
<body>
<app-root></app-root>
</body>
</html>Change colors
Override the variables in your global styles, after the NgDoc styles. A rule on :root changes the light theme; add a rule for [data-theme='dark'] to change the dark theme too:
:root {
--ng-doc-primary: #7c3aed;
--ng-doc-font-family: 'Inter', sans-serif;
}
:root[data-theme='dark'] {
--ng-doc-primary: #a78bfa;
}
@media (prefers-color-scheme: dark) {
:root[data-theme='auto'] {
--ng-doc-primary: #a78bfa;
}
}The auto theme uses the dark values inside prefers-color-scheme: dark, so repeat your dark overrides there.
Tints, borders, focus rings and badges are mixed from the main colors, so they follow your overrides. For example, the background of a selected search result is a tint of --ng-doc-primary.
Main variables
| Variable | Description |
|---|---|
--ng-doc-base-0 to --ng-doc-base-10 | The neutral ramp. base-0 is the page background, and each step moves further from it. |
--ng-doc-background | The page background. --ng-doc-base-0 by default. |
--ng-doc-text | Body text. |
--ng-doc-text-muted | Secondary text, such as descriptions and hints. |
--ng-doc-heading-color | Headings and emphasized text. |
--ng-doc-link-color | Links. --ng-doc-primary by default. |
--ng-doc-border-color | Borders and dividers. |
--ng-doc-primary | The accent color: active items, buttons and focus. |
--ng-doc-info, --ng-doc-success | The colors of the note and success callouts. |
--ng-doc-warning, --ng-doc-alert | The colors of the warning and alert callouts. |
--ng-doc-primary-text and the other -text | Text on a solid fill of that color, such as --ng-doc-alert-text. |
--ng-doc-font-family | The body font. |
--ng-doc-heading-font-family | The heading font. |
--ng-doc-font-size | The body font size. |
--ng-doc-code-font | The code font. |
--ng-doc-code-background | The background of code blocks. |
--ng-doc-inline-code-background | The color that inline code is tinted with. |
--ng-doc-shadow-color | The color of every shadow. |
--ng-doc-class-background and the other kinds | The hue of an API kind, such as a class or an interface. |
The sizes of the navbar, the sidebar and the page are in
Tokens
The default values come from a token layer in @ng-doc/ui-kit: palettes such as --ng-doc-palette-brand-600, spacing (--ng-doc-space-4), radii (--ng-doc-radius-md) and type sizes. You can use the tokens in your own styles to match NgDoc. Prefer overriding the variables above to overriding tokens, because the variables are what the components read.
Custom theme
A custom theme is a stylesheet scoped to its own data-theme value. Start from the dark theme, which overrides only what differs from the light values:
// dark theme
@mixin theme {
--ng-doc-base-rgb: 24 25 29;
--ng-doc-base-0: var(--ng-doc-palette-neutral-950);
--ng-doc-base-1: var(--ng-doc-palette-neutral-900);
--ng-doc-base-2: var(--ng-doc-palette-neutral-875);
--ng-doc-base-3: var(--ng-doc-palette-neutral-850);
--ng-doc-base-4: var(--ng-doc-palette-neutral-800);
--ng-doc-base-5: var(--ng-doc-palette-neutral-750);
--ng-doc-base-6: var(--ng-doc-palette-neutral-700);
--ng-doc-base-7: var(--ng-doc-palette-neutral-600);
--ng-doc-base-8: var(--ng-doc-palette-neutral-500);
--ng-doc-base-9: var(--ng-doc-palette-neutral-450);
--ng-doc-base-10: var(--ng-doc-palette-neutral-400);
--ng-doc-heading-color: var(--ng-doc-palette-neutral-50);
--ng-doc-text: var(--ng-doc-palette-neutral-300);
--ng-doc-text-muted: var(--ng-doc-base-9);
--ng-doc-text-selection: color-mix(in srgb, var(--ng-doc-primary) 30%, transparent);
--ng-doc-shadow-color: rgb(0 0 0 / 0.45);
--ng-doc-inline-code-background: var(--ng-doc-base-10);
// One accent family in both themes: links, info and primary share the brand hue.
--ng-doc-primary: var(--ng-doc-palette-brand-400);
--ng-doc-primary-text: var(--ng-doc-palette-neutral-1000);
--ng-doc-link-color: var(--ng-doc-primary);
--ng-doc-info: var(--ng-doc-palette-brand-400);
--ng-doc-info-text: var(--ng-doc-palette-neutral-1000);
--ng-doc-success: var(--ng-doc-palette-green-400);
--ng-doc-success-text: var(--ng-doc-palette-neutral-1000);
--ng-doc-warning: var(--ng-doc-palette-amber-400);
--ng-doc-warning-text: var(--ng-doc-palette-neutral-1000);
--ng-doc-alert: var(--ng-doc-palette-red-400);
--ng-doc-alert-text: var(--ng-doc-palette-neutral-1000);
// The search highlight stays yellow, as in the light theme.
--ng-doc-mark-background: color-mix(in srgb, #f5c542 28%, transparent);
--ng-doc-search-result-color: var(--ng-doc-text);
--ng-doc-navbar-border: 1px solid var(--ng-doc-border-color);
// Derived tokens: lighter hues and slightly stronger tints on the dark page.
--ng-doc-hue-violet: var(--ng-doc-palette-violet-400);
--ng-doc-on-hue: var(--ng-doc-palette-neutral-1000);
--ng-doc-mix-soft: 12%;
--ng-doc-mix-chip: 16%;
--ng-doc-mix-border: 30%;
--ng-doc-focus-ring-color: var(--ng-doc-palette-brand-400);
// base-7 input borders measure below 3:1 on the base-1 inspector, so its inputs use base-8.
--ng-doc-playground-input-border: var(--ng-doc-border-size) solid var(--ng-doc-base-8);
}
// shiki theme to match dark theme
@mixin shiki-theme {
.shiki,
.shiki span {
color: var(--shiki-dark) !important;
}
}
// enable dark theme when using auto theme and prefers-color-scheme is dark
:root[data-theme='auto'] {
@media (prefers-color-scheme: dark) {
@include theme();
@include shiki-theme();
}
}
// apply dark theme when dark theme is selected
:root[data-theme='dark'] {
@include theme();
@include shiki-theme();
}For a theme called ocean, add the rules to your global styles:
:root[data-theme='ocean'] {
--ng-doc-base-0: #0b1f2a;
--ng-doc-base-1: #102a38;
--ng-doc-heading-color: #e6f4f8;
--ng-doc-text: #c2dde6;
--ng-doc-primary: #38bdf8;
}
/* Code blocks: use the dark colors of the code theme */
:root[data-theme='ocean'] .shiki,
:root[data-theme='ocean'] .shiki span {
color: var(--shiki-dark) !important;
}The last rule is needed only for a dark custom theme whose code blocks use a pair of Shiki themes (the legacy builders, or shiki.themes in the configuration): code blocks use the light colors of the code theme unless the theme is dark or auto. With the default css-variables code theme, set --ng-doc-syntax-* in your theme instead.
Switch to it with , or set it by default in index.html:
import { ChangeDetectionStrategy , Component , computed , inject } from '@angular/core';
import { NgDocThemeService } from '@ng-doc/app';
@Component ({
selector: 'app-theme-button',
template: ` <button type="button" [attr.aria-pressed]="isOcean()" (click)="toggle()">Ocean theme</button> `,
changeDetection: ChangeDetectionStrategy .OnPush,
})
export class ThemeButtonComponent {
private readonly themeService = inject (NgDocThemeService );
protected readonly isOcean = computed (() => this.themeService.theme() === 'ocean');
protected toggle(): void {
this.themeService.set(this.isOcean() ? 'auto' : 'ocean');
}
}theme() is the current theme as a signal: auto, dark, the id of your theme, or null for the light theme. set() changes it and saves it in the browser; set() without an id switches to the light theme.
Code highlighting
With the new engine (the Vite host and the ng-doc CLI), code is colored by NgDoc's css-variables theme by default: every token takes a CSS variable of the current site theme, so code follows the light, dark and custom themes. Override the variables like the others:
:root {
--ng-doc-syntax-keyword: #8250df;
--ng-doc-syntax-type: #0550ae;
--ng-doc-syntax-function: #116329;
--ng-doc-syntax-string: #0a3069;
}The variables are --ng-doc-syntax-plain, -punctuation, -comment, -keyword, -type, -function, -string, -number, -tag and -decorator. The legacy application and dev-server builders keep the github-light and ayu-dark Shiki themes unless you set css-variables as both themes. To use other Shiki themes, see
Gotchas
WarningThe
component offers only Auto, Light and Dark. While a custom theme is set, it shows Auto, and pressing it leaves your theme. Give readers your own control for a custom theme.ng-doc-theme-toggle
💡 TipOverride variables in a global stylesheet. A rule in a component's styles is scoped to that component and doesn't reach NgDoc.
Next: