Theming
GHDS is built to be re-skinned. Every color a component paints resolves through a live
comp → sys → ref chain of CSS custom properties, so overriding one semantic
variable re-themes everything that uses it — without touching component code or forking the
library.
How theming works
@ghds/tokens emits its CSS variables as a reference chain, not
as flat literals. A component reads its own --comp-* variable, which aliases a
semantic --sys-* variable, which in turn aliases a raw --ref-* value:
--ref-palette-brand-600: #3e47c9; /* raw value */
--sys-color-bg-primary-default: var(--ref-palette-brand-600); /* semantic role */
--comp-button-bg-primary-default: var(--sys-color-bg-primary-default); /* component */
Because the aliases stay live at runtime, redefining any link in the chain cascades downward.
Override --sys-color-bg-primary-default and every component that maps to the
primary role — buttons, badges, links, focus rings — updates at once.
Customizing in three steps
1. Load the token stylesheet
Import it once, at your app's entry point. This defines every default variable:
import '@ghds/tokens/css'; 2. Override the variables you want
In your own global stylesheet, redefine the semantic variables under :root. You
never edit component code — you re-point the tokens they already consume:
:root {
--sys-color-bg-primary-default: #0969da;
--sys-color-bg-primary-hover: #0757ba;
--sys-color-text-link: #0969da;
--sys-color-border-focus: #218bff;
} 3. Cover dark mode
GHDS switches themes with a data-theme="dark" attribute (falling back to
prefers-color-scheme). The dark theme re-declares the semantic variables, so set
your dark values at the same specificity or they'll be overridden:
[data-theme="dark"] {
--sys-color-bg-primary-default: #218bff;
--sys-color-text-link: #6cb6ff;
} Which layer should I override?
-
--sys-*(semantic) — start here. The safest, highest-leverage surface. Each variable is a role (primary,danger,text-link…), so an override reads clearly and reaches every component that plays that role. The playground below edits this layer. -
--ref-*(palette) — for a whole-palette reskin. Redefining--ref-palette-brand-600shifts every semantic token that references it, in one move. Use when you're changing the underlying color ramp, not a single role. -
--comp-*(component) — for one component only. Override--comp-button-bg-primary-defaultto retune a single component without affecting anything else that shares its semantic token.
The full list of semantic variables and their default light/dark values lives on the Design Style page.
Playground
Adjust the semantic colors and watch real GHDS components re-theme. Switch between Light and
Dark to set each theme's values independently — the generated CSS emits a :root
block and a [data-theme="dark"] block, ready to paste into your stylesheet.