Set colors and themes
Choose a layout preset and control colors in light and dark mode.
Set theme, colors, and appearance in your docs folder’s docs.json to apply your brand without writing CSS. Use x-margin.tokens when you need control over individual surfaces or text colors.
The examples below are separate fragments to merge into your existing docs.json. Keep your other settings, including navigation, and deploy the changes before checking the published site.
Choose a theme preset
The theme field selects a Margin layout preset and its starting palette. Margin approximates the Mintlify layout; it does not reproduce the Mintlify theme pixel for pixel.
For example, select the aspen theme:
{
"theme": "aspen"
}Use these mappings to choose a layout. Themes that share a layout keep their own palette, and some restyle parts of it: linden sets monospace type, and willow sets serif headings on a tinted sidebar.
theme | Margin layout preset | Look |
|---|---|---|
mint | neutral | Two-row header, tinted active rows, contents without a rail |
linden | neutral | Mint’s layout on cream, in monospace |
maple | warm | Header in the sidebar, a rail under each group |
almond | warm | Compact header, tinted active rows, contents rail |
palm | verdant | Tinted header, sidebar edge, accent-only active rows |
willow | verdant | One-row header, tinted sidebar, serif headings |
aspen | aspen | Rounded search, uppercase group labels with dividers |
sequoia | dusk | Tinted tab row, edges on sidebar and contents |
luma | contrast | One-row header with pill tabs |
Omitting theme uses mint. An unknown theme falls back to mint with a diagnostic. Use the names in the first column as configuration values, not the layout names.
Every preset keeps text readable in light and dark mode: body text, muted text, and your accent color reach at least a 4.5:1 contrast ratio against the surfaces they appear on.
Set site colors
The colors object controls the brand color. Set primary as the base, then optionally set light and dark:
{
"colors": {
"primary": "#0F5A3C",
"light": "#6EE7B7",
"dark": "#0F5A3C"
}
}The dark and light names describe the color’s brightness, not the page mode:
| Field | Effect |
|---|---|
colors.primary | Accent for links, the active page, and highlights in light mode, and the fallback for the other two fields. |
colors.light | Accent in dark mode; falls back to primary. |
colors.dark | Fill for buttons in both modes; falls back to primary. |
Margin keeps your accent readable. If a color is too light for light mode or too dark for dark mode to reach a 4.5:1 contrast ratio on the page and its panels, Margin adjusts only its lightness until it does. For example, a pale yellow primary becomes a darker amber on white pages, and a navy primary becomes a lighter slate in dark mode. Colors that already pass are used as written. If no lightness works on both the page and its panels, for example when you set a black light-mode background, Margin makes the color readable on the page, where links appear, or keeps it as written. Button text is black or white, whichever reads better on the button color.
Color values must use #RGB or #RRGGBB hex notation. Named colors, rgb(), and alpha hex values are not supported in these fields. Invalid values produce a field_invalid diagnostic rather than applying the color.
If colors is omitted, Margin can derive an accent from the logo; otherwise the preset supplies the starting colors. Setting "colors": null keeps the selected preset’s tokens and disables derived and configured token overrides, including x-margin.tokens and background.color. It does not disable a separate site stylesheet. Omit colors, rather than setting it to null, if you want to configure tokens directly.
Configure light and dark mode
The appearance object controls the initial mode and whether readers can switch modes. Its default accepts system, light, or dark; omission uses system.
To start with the reader’s system preference and keep the mode switch available, use:
{
"appearance": {
"default": "system",
"strict": false
}
}With strict omitted or false, readers can change the mode, and a saved choice can take precedence over the initial default. To force light mode or dark mode, set default to that mode and strict to true. Strict mode hides the mode switch. With default: "system", strict mode hides the switch but does not force a fixed light or dark mode.
Mode selection is separate from mode-specific colors. The active mode selects the matching colors and token values; changing appearance does not replace the chosen theme.
For an explicit background color in each mode, set background.color as a pair:
{
"background": {
"color": {
"light": "#FFFFFF",
"dark": "#101814"
}
}
}Override design tokens
A design token names a reusable color, such as a card background or border. Set tokens in x-margin.tokens using the short names below, not CSS variable names. Each value is either a hex string shared by both modes or an object with both light and dark hex strings. Unlike colors.light and colors.dark, the keys in a token pair name the page mode directly.
This example sets a shared border color and mode-specific card and primary colors. The explicit primary-foreground pair sets the text color used on primary-colored surfaces:
{
"x-margin": {
"tokens": {
"border": "#64748B",
"card": {
"light": "#F0FDF4",
"dark": "#14251C"
},
"primary": {
"light": "#0F5A3C",
"dark": "#6EE7B7"
},
"primary-foreground": {
"light": "#FFFFFF",
"dark": "#052E16"
}
}
}
}The supported token names are:
| Purpose | Token names |
|---|---|
| Page | background, foreground |
| Primary surfaces | primary, primary-foreground |
| Secondary surfaces | secondary, secondary-foreground |
| Muted surfaces | muted, muted-foreground |
| Accent surfaces | accent, accent-foreground |
| Boundaries and focus | border, ring |
| Cards | card, card-foreground |
| Popovers | popover, popover-foreground |
| Status colors | info, warning, error |
Unknown token names are ignored. radius, font names, layout dimensions, and raw --color-fd-* names are not supported keys in x-margin.tokens. Token colors use the same hex formats as colors. Supply both members of a mode pair; a single-member object is not a supported override.
For the primary color, precedence from highest to lowest is a matching site stylesheet rule, x-margin.tokens.primary, the applicable colors value, a detected logo accent, then the preset default. Margin uses x-margin.tokens and site stylesheet values as written, without adjusting their contrast. Direct token overrides also take precedence over corresponding settings such as background.color. A site stylesheet is applied after the token block and can override token values through the CSS cascade.
Margin chooses black or white primary-foreground text in each mode, whichever reads better on the primary color, unless you set primary-foreground yourself.
After deployment, switch between light and dark mode and check cards, borders, and primary-colored surfaces. For the token example above, run this expression in the browser console to check the active primary token:
getComputedStyle(document.documentElement)
.getPropertyValue("--color-fd-primary")
.trim()Without a stylesheet overriding it, the expression returns #0F5A3C in light mode and #6EE7B7 in dark mode. If the value differs, check for colors: null, an invalid hex value, or a site stylesheet rule overriding the token.