Overview

Blueprint 6 styles its components from CSS custom properties in the --bp-* namespace (verified in 6.21): intent colors, a palette, surface values, typography colors, and focus-ring settings, all defined on :root in blueprint.css. Override those tokens to retheme. Class names keep the bp6- prefix. Package setup is in blueprint.

Override --bp-* tokens, not component CSS

Set tokens on :root (or a scope) after Blueprint’s stylesheet loads. Intent colors come in five states, so override all five together.

:root {
  --bp-intent-primary-rest: #1f5fbf;
  --bp-intent-primary-hover: #194d9c;
  --bp-intent-primary-active: #143d7d;
  --bp-intent-primary-disabled: #6f9be0;
  --bp-intent-primary-foreground: #ffffff;
}

Provide the full intent set (default, primary, success, warning, danger) whenever you change one, so intents stay distinct. Other groups: --bp-palette-*, --bp-surface-* (borders, shadows, background colors, --bp-surface-border-radius, --bp-surface-spacing), --bp-typography-color-*, and --bp-emphasis-focus-*. Inspect :root in DevTools for the current list, since new tokens appear in minor releases.

Check contrast: --bp-intent-primary-foreground on --bp-intent-primary-rest needs 4.5:1 for button text. If the brand color fails, darken the token and keep the bright brand color for decoration.

Treat compiled Sass overrides as ineffective

$pt-* Sass variables (such as $pt-grid-size) exist in @blueprintjs/core/lib/scss/variables.scss for your own Sass. Setting them before importing the compiled blueprint.css changes nothing, because that CSS is already compiled, and colors come from the --bp-* tokens. Verify any Sass-based override in the rendered output.

Toggle dark mode on a high ancestor

Dark mode applies when .bp6-dark or data-bp-color-scheme="dark" is on an ancestor. Put it on <html> so portal-rendered overlays, which mount on document.body, are covered too.

useEffect(() => {
  document.documentElement.classList.toggle("bp6-dark", dark);
}, [dark]);

Read the stored preference (and prefers-color-scheme as the fallback) before first render to avoid a flash. For a themed custom container, add the class on that element; see blueprint-overlays for the portal rules.

Override dark surface tokens inside the dark scope

The dark scope redefines only surface (borders, shadows, default background) and default typography tokens. Where .bp6-dark sits below :root on a wrapper element, its own definitions beat an inherited :root override, so repeat the override under the dark selector. Intent colors are shared by both modes.

.bp6-dark {
  --bp-surface-background-color-default-rest: #0b0f14;
}

Do not patch compiled CSS or depend on internals

Editing node_modules/.../blueprint.css breaks on every install. For a one-off adjustment, scope a rule to your own wrapper class, for example .my-compact-table .bp6-table-cell { padding: 2px 6px; }. Blueprint does not guarantee class names across minor versions, so prefer tokens for anything systemic.

Keep visible focus for keyboard users

FocusStyleManager.onlyShowFocusOnTabs() hides focus rings after a mouse click and restores them for keyboard navigation. Call it once at startup, and skip it for apps with heavy keyboard or screen-reader use. Tune the ring itself with --bp-emphasis-focus-color, -width, and -offset. See accessibility.