On this page ▾
Theming
NgMd is built on Tailwind v4 with CSS variables for theme tokens. Rebrand in one file: src/styles.css. The fuchsia accent you see across the site is the default, not a baked-in choice. No component in this repo hardcodes a Tailwind colour like text-fuchsia-500; every accent-aware class reads var(--accent) instead, so swapping one token re-skins the whole site.
Token groups
The token block lives under @layer base in src/styles.css. Four groups, declared twice (once under :root for light, once under .dark for dark mode):
Surface
--bg: #ffffff;
--bg-muted: #f4f4f5;
--fg: #0a0a0a;
--muted: #71717a;
--border: #e4e4e7;
--border-strong: #d4d4d8;
--bg-muted is for card backgrounds, callout bodies, header surfaces. --border-strong is for hover states where the regular border should darken.
Brand
--primary: #18181b;
--primary-fg: #fafafa;
--accent: #d946ef;
--accent-strong: #a21caf;
--accent-fg: #ffffff;
--accent-soft: rgba(217, 70, 239, 0.12);
--accent-gradient: linear-gradient(
to right,
#f43f5e 0%,
#d946ef 50%,
#a855f7 100%
);
--accent-gradient-soft: linear-gradient(
to bottom right,
rgba(244, 63, 94, 0.10) 0%,
rgba(217, 70, 239, 0.10) 50%,
rgba(168, 85, 247, 0.10) 100%
);
--code-border-gradient: linear-gradient(135deg, #f0abfc, #d946ef, #a21caf);
--line-highlight: rgba(217, 70, 239, 0.12);
Eight accent tokens cover everything:
| Token | What it's for |
|---|---|
--accent |
Card icons, link hover, focus rings, code-preview headings, the "live" tag |
--accent-strong |
Active sidebar item, active TOC heading. Deeper saturation reads better on light surfaces |
--accent-fg |
Foreground colour to pair with a solid --accent surface (rare; used by adjacent components) |
--accent-soft |
Tinted background for active rows in the palette, sidebar, and TOC |
--accent-gradient |
Hero title fill, homepage hero band, logo stroke |
--accent-gradient-soft |
Hero background wash, homepage spotlight backdrop |
--code-border-gradient |
Gradient border on inline code chips in prose |
--line-highlight |
Background of lines highlighted with {1,3-5} in a code fence |
Geometry
--radius-sm: 0.25rem;
--radius: 0.5rem;
--radius-lg: 0.75rem;
--radius-xl: 1rem;
Typography
--font-sans: Inter, ui-sans-serif, system-ui, -apple-system,
BlinkMacSystemFont, sans-serif;
--font-display: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo,
monospace;
--font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
--font-display powers the wordmark in the header, --font-sans is the default body face, --font-mono is for inline code and code blocks.
Light / dark mode
NgMd uses class-based dark mode. The ThemeService toggles a dark class on <html>:
root.classList.toggle('dark', resolved === 'dark');
The mode cycles light, dark and auto, and is persisted in localStorage. Auto (the default on first visit) follows prefers-color-scheme. An inline boot script in index.html sets the class before Angular bootstraps so there is no flash on refresh.
Picking a brand colour
:root and .dark with a slightly lighter shade for dark mode so contrast stays readable.
Pick one accent and update its companion tokens in both :root and .dark. The --accent-soft is the same hue at 10-15% opacity; --accent-strong is a deeper shade for active text on light surfaces:
:root {
--accent: #dd0031; /* example: Angular red */
--accent-strong: #991b1b; /* deeper for active text on light bg */
--accent-soft: rgba(221, 0, 49, 0.12);
}
.dark {
--accent: #ef4444; /* lighter for dark backgrounds */
--accent-strong: #fca5a5; /* lighter still for active text on dark */
--accent-soft: rgba(239, 68, 68, 0.15);
}
For a full rebrand, also update --accent-gradient and --accent-gradient-soft with the colours you want in the hero wash (in both blocks: .dark uses lighter stops, #fb7185, #e879f9 and #c084fc, so gradient text stays bright on the dark background), and --code-border-gradient and --line-highlight for inline code chips and highlighted code lines.
Components that lean on the accent (sidebar active item, TOC active heading, command palette row, page footer hover, heading anchor hover, card icon, card CTA arrow, pill hover, hero gradient, code-preview headings, install-picker tabs) all pick the new colour up automatically.
--code-border-gradient. Inside cards and callouts it drops the border and renders as a plain muted chip, so it doesn't compete with the surrounding box.
How components consume tokens
Tailwind v4 supports arbitrary-value classes that read a CSS variable directly. NgMd uses this pattern wherever a component needs the accent:
<!-- text colour from --accent -->
<span class="text-[color:var(--accent)]">Active</span>
<!-- background tint from --accent-soft -->
<div class="bg-[color:var(--accent-soft)]">Highlighted row</div>
<!-- hover state from --accent -->
<a class="hover:text-[color:var(--accent)] hover:border-[color:var(--accent)]">Link</a>
<!-- gradient on title via bg-clip-text -->
<h1 class="bg-clip-text text-transparent" style="background-image: var(--accent-gradient)">Hero</h1>
Why this matters: the Tailwind shade utilities (text-fuchsia-500, bg-rose-100/10) bake the colour into the class name and survive a token swap untouched. The bracket syntax reads the variable at render time, so any change to --accent in :root / .dark propagates through the whole site without touching component code.
bg-[image:var(...)] reliably. NgMd uses style="background-image: var(--accent-gradient)" for hero and spotlight elements (same CSS variable, just dropped into the inline style attribute so it always works regardless of class generation).
When an active state needs to win against a static text-zinc-500 (or similar base utility), append ! to bump specificity:
<a [class]="isActive ? 'bg-[color:var(--accent-soft)]! text-[color:var(--accent-strong)]!' : ''">
Item
</a>
Custom fonts
Self-host or load from a CDN, then swap the token:
:root {
--font-sans: 'YourFont', Inter, system-ui, sans-serif;
}
For self-hosted fonts, declare an @font-face rule at the top of styles.css.
Reaching outside the tokens
For one-off styling beyond the token system, use Tailwind utilities directly. Any colour from the Tailwind palette works out of the box:
<a class="bg-blue-600 hover:bg-blue-700 text-white">Custom</a>
Typography plugin
Long-form markdown content uses @tailwindcss/typography's prose class. Override prose tokens with CSS variables under .prose to tune your reading experience.