Theming
Light and dark mode, the --sbk-* CSS custom properties, fonts, and isolation from your app's global styles.
Every color in the stylesheet is a --sbk-* CSS custom property, measured from Slack’s own Block Kit
Builder. Dark mode is a matter of which values are active. You rarely need to override them, but
they’re there when you do.
Light and dark mode
By default, dark values apply under prefers-color-scheme: dark: the page follows the visitor’s OS
setting, same as Slack’s own desktop client.
To force a theme regardless of OS preference, set data-theme on <html> (or any ancestor of your
Block Kit content):
<html data-theme="dark"></html>
<html data-theme="light"></html>
data-theme="light" also works as an escape hatch to opt an element back out of dark mode even when
the OS prefers it.
The theme prop
<BlockKitProvider theme="light" | "dark"> sets data-theme on a wrapper <div> around its children,
and on the menus, tooltips and dialogs it opens outside that wrapper. It’s useful for previewing both
themes side by side on the same page, independent of the OS setting:
<div style={{ display: "flex", gap: 16 }}>
<BlockKitProvider theme="light">
<Message blocks={blocks} />
</BlockKitProvider>
<BlockKitProvider theme="dark">
<Message blocks={blocks} />
</BlockKitProvider>
</div>
Leave theme unset to follow the page’s own data-theme/prefers-color-scheme instead.
Slack’s other dark themes
Slack offers several dark themes; the dark values follow its default one. Callout backgrounds and
area chart fills in dark mode are derived from that palette rather than measured. To match another
theme, override the tokens under [data-theme="dark"]:
[data-theme="dark"] {
--sbk-callout-green-bg: #1f3a2c;
--sbk-chart-area-1: #5c3320;
}
CSS custom properties
The full set lives in base.css and Message.css. Override any of them after importing the
stylesheet to restyle without touching the components. The main tokens:
--sbk-font?string
Body font. See Fonts below.
string"Slack-Lato", Lato, sans-serif--sbk-font-mono?string
Code font.
string"Slack-Roboto-Mono", "Roboto Mono", monospace--sbk-text?color
Primary text color.
color--sbk-muted?color
Secondary/muted text, e.g. timestamps.
color--sbk-bg?color
Surface background (message, modal, Home tab).
color--sbk-link?color
Link and mention text color.
color--sbk-mention-bg?color
Resolved user/channel mention background.
color--sbk-primary?color
Primary button background (e.g. modal Submit).
color--sbk-danger?color
Danger-styled button background.
color--sbk-border?color
Default hairline border color.
color--sbk-divider?color
Divider block color.
color--sbk-code-text?color
Inline code and fenced code block text.
color--sbk-code-bg?color
Inline code and fenced code block background.
color--sbk-focus-ring?color
Keyboard focus ring and focused input border.
color--sbk-menu-bg?color
Dropdown/select menu background.
color--sbk-tooltip-bg?color
Tooltip background.
color--sbk-callout-green-bg?color
Callout background, one per `background_color`: green, blue, red, yellow, purple, gray.
color--sbk-chart-area-1?color
Area chart fill, one per series color: `--sbk-chart-area-1` to `-4`.
color:root {
--sbk-primary: #1264a3;
--sbk-primary-hover: #0b4c80;
}
Fonts
Slack sets body text in Lato and code in Roboto Mono, but Slack’s own font files aren’t redistributable. Install the open-source builds from Fontsource instead:
npm install @fontsource/lato @fontsource/roboto-monopnpm add @fontsource/lato @fontsource/roboto-monoyarn add @fontsource/lato @fontsource/roboto-monobun add @fontsource/lato @fontsource/roboto-mononub add @fontsource/lato @fontsource/roboto-monoaube add @fontsource/lato @fontsource/roboto-monoimport "@fontsource/lato/400.css";
import "@fontsource/lato/400-italic.css";
import "@fontsource/lato/700.css";
import "@fontsource/lato/900.css";
import "@fontsource/roboto-mono/400.css";
The stylesheet asks for Slack-Lato first, then falls back to plain Lato, so if you’re already
serving Lato yourself (a CDN, self-hosted @font-face), you can skip installing Fontsource: any
font-family: Lato declaration is picked up.
Isolation from your app’s global CSS
Every component’s root carries an sbk-root class (portalled dialogs and tooltips get it too), and
the stylesheet rolls everything under it back to the browser’s defaults before applying its own rules:
:is(.sbk-root, .sbk-confirm__overlay, .sbk-tooltip)
:where(:not(svg, svg *, img, video, canvas, iframe, embed, object)) {
all: revert;
}
This means global resets in your app (Tailwind’s preflight, a docs theme’s heading font, a blanket
* { min-width: 0 }) don’t leak into how a block renders, and the reverse: block styles don’t leak
into your app either, since everything is scoped under .sbk-root. You don’t need to configure
anything for this; it’s automatic once you import @nkootstra/block-kit/styles.css.