Design Tokens
Free themeThe CSS custom-property contract BuddyX exposes for theme CSS, child themes, and plugin integrations. Reference these --bx-* variables instead of hard-coded colors, radii, or spacing so your styles inherit the customizer, the active style variation, and light/dark mode automatically.
What tokens are
BuddyX emits a single block of CSS custom properties into an inline stylesheet on every front-end render. inc/Tokens/Component.php reads customizer theme_mod values, merges them with framework defaults, and prints a :root { … } rule (plus a dark override rule). Every stylesheet in the theme, and everything you write in a child theme, should consume the token names rather than raw values:
.my-card {
background: var(--bx-color-bg-elevated);
color: var(--bx-color-fg);
border: 1px solid var(--bx-color-border);
border-radius: var(--bx-radius-card);
padding: var(--bx-space-card);
box-shadow: var(--bx-shadow-card-md);
}
Because the value lives in one variable, a brand change in the customizer, a style-variation swap, or a dark-mode toggle repaints your CSS with no further work.
Naming convention
--bx-{kind}-{role}-{state?}
| Segment | Values |
|---|---|
kind |
color, radius, space, shadow, duration, easing, z |
role |
semantic identifier (accent, fg, bg, link, button, header, card, …) |
state |
optional suffix (-hover, -active, -bg, -fg, -strong, -muted) |
Reference tokens by name only. Never copy the resolved hex or px value into your CSS. That is the one rule that keeps mode swaps and rebrands to a single variable change.
The 3-layer model
The final value of any token is resolved through three layers that build_token_css() prints in cascade order. Later layers win.
| Layer | Source | Emitted | Purpose |
|---|---|---|---|
| 1. Framework defaults | $framework_tokens in inc/Tokens/Component.php |
Always, regardless of settings | Guarantees every token is present (neutrals, spacing, shadows, motion, z-index) so consumer CSS never hits an undefined variable. |
| 2. Customizer values | theme_mods mapped in $simple_color_tokens, $typography_color_tokens, $dimension_tokens |
When site_custom_colors is enabled and the customer saved a non-default value |
The site owner's colors, radii, and typography colors override the framework baseline. |
| 3. Mode + variation overlay | $dark_defaults and the active style variation |
Dark set via :root[data-bx-mode="dark"]; a dark style variation routes its palette into the same block |
Repaints tokens for dark mode / the selected preset without touching consumer CSS. |
A fourth, non-authoritative surface rides alongside these: legacy aliases (see below) that point old variable names at the canonical --bx-* tokens for backward compatibility.
Data flow:
theme_mod -> Tokens::collect_mods() -> build_token_css() -> <style>:root { --bx-… : …; }
-> <style>:root[data-bx-mode="dark"] { --bx-… : …; }
Framework tokens emit even when the site_custom_colors master toggle is off, so neutrals, spacing, shadows, and motion are always available.
Token families
Color - brand and buttons
| Token | Customizer setting | Purpose |
|---|---|---|
--bx-color-accent |
site_primary_color |
Primary brand color |
--bx-color-button-bg |
site_buttons_background_color |
Button surface |
--bx-color-button-bg-hover |
site_buttons_background_hover_color |
Button hover surface |
--bx-color-button-fg |
site_buttons_text_color |
Button text |
--bx-color-button-fg-hover |
site_buttons_text_hover_color |
Button hover text |
--bx-color-button-border |
site_buttons_border_color |
Button border (defaults to button bg) |
--bx-color-button-border-hover |
site_buttons_border_hover_color |
Button hover border |
--bx-color-accent-secondary |
framework default | Variation accent slot (teal) |
--bx-color-accent-tertiary |
framework default | Variation accent slot (yellow) |
Brand-driven bases (--bx-color-accent, --bx-color-button-bg, --bx-color-link, --bx-color-bg, --bx-color-bg-elevated, --bx-color-header-bg) also emit derived -rgb / -hover / -active / -focus / -bg / -border / -disabled / -inverse variants, so hover and focus states follow a rebrand automatically.
Color - surfaces
| Token | Source | Purpose |
|---|---|---|
--bx-color-bg |
body_background_color |
Page background |
--bx-color-bg-page |
content_background_color |
Centered content frame |
--bx-color-bg-elevated |
box_background_color |
Cards / boxes |
--bx-color-bg-muted |
secondary_background_color |
Quiet panels |
--bx-color-bg-subtle |
framework default | Very-light surface tint |
--bx-color-bg-overlay |
framework default | Modal / mobile-menu scrim |
Color - text and links
| Token | Source | Purpose |
|---|---|---|
--bx-color-fg |
typography_option[color] |
Body text |
--bx-color-fg-muted |
framework default | Mid-tone / meta text (WCAG AA on white) |
--bx-color-fg-subtle |
framework default | Placeholder / subtle text |
--bx-color-fg-inverse |
framework default | Text on a color surface |
--bx-color-link |
site_links_color |
Hyperlink default |
--bx-color-link-hover |
site_links_focus_hover_color |
Hyperlink hover |
--bx-color-h1 … --bx-color-h6 |
h1-h6_typography_option[color] |
Heading colors |
Color - header, menu, footer
| Token | Source | Purpose |
|---|---|---|
--bx-color-header-bg |
site_header_bg_color |
Site header surface |
--bx-color-site-title |
site_title_typography_option[color] |
Site title text |
--bx-color-site-title-hover |
site_title_hover_color |
Site title hover |
--bx-color-site-tagline |
site_tagline_typography_option[color] |
Tagline |
--bx-color-menu-fg |
menu_typography_option[color] |
Menu link |
--bx-color-menu-hover |
menu_hover_color |
Menu hover |
--bx-color-menu-active |
menu_active_color |
Menu active |
--bx-color-subheader-fg |
site_sub_header_typography[color] |
Sub-header text |
--bx-color-loader-bg |
site_loader_bg |
Page loader background |
--bx-color-footer-title |
site_footer_title_color |
Footer titles |
--bx-color-footer-fg |
site_footer_content_color |
Footer body text |
--bx-color-footer-link |
site_footer_links_color |
Footer link |
--bx-color-footer-link-hover |
site_footer_links_hover_color |
Footer link hover |
--bx-color-copyright-bg |
site_copyright_background_color |
Copyright surface |
--bx-color-copyright-border |
site_copyright_border_color |
Copyright divider |
--bx-color-copyright-fg |
site_copyright_content_color |
Copyright text |
--bx-color-copyright-link |
site_copyright_links_color |
Copyright link |
--bx-color-copyright-link-hover |
site_copyright_links_hover_color |
Copyright link hover |
Color - structural, state, forms
These have no customizer field. They are framework-supplied neutrals introduced to remove hard-coded hex values from the stylesheets, and each has a dark counterpart.
| Group | Tokens |
|---|---|
| Structural | --bx-color-border, --bx-color-border-strong, --bx-color-divider, --bx-color-shadow, --bx-color-shadow-strong |
| State | --bx-color-success / -bg, --bx-color-warning / -bg, --bx-color-error / -bg, --bx-color-info / -bg |
| Community / presence | --bx-color-presence-online, --bx-color-presence-away, --bx-color-presence-busy, --bx-color-presence-offline, --bx-color-bp-friend, --bx-color-bp-favorite |
| Forms | --bx-color-input-bg, --bx-color-input-border, --bx-color-input-focus-border, --bx-color-input-fg, --bx-color-input-placeholder |
Radius
| Token | Source | Default |
|---|---|---|
--bx-radius-global |
site_global_border_radius |
Global UI radius |
--bx-radius-button |
site_button_border_radius |
Button radius |
--bx-radius-form |
site_form_border_radius |
Form input radius |
--bx-radius-card |
framework default | 12px |
--bx-radius-pill |
framework default | 999px |
Spacing
| Token | Default | Purpose |
|---|---|---|
--bx-space-section |
clamp(40px, 8vw, 80px) |
Vertical rhythm between sections |
--bx-space-card |
24px |
Card / panel padding |
--bx-space-stack |
12px |
Vertical gap between siblings |
--bx-space-inline |
8px |
Inline gap (icon + text) |
Shadows
| Token | Default |
|---|---|
--bx-shadow-card-sm |
0 1px 2px 0 var(--bx-color-shadow) |
--bx-shadow-card-md |
0 4px 12px -2px var(--bx-color-shadow) |
--bx-shadow-card-lg |
0 12px 32px -4px var(--bx-color-shadow-strong) |
The shadow ladder references the --bx-color-shadow* color tokens, so shadows deepen automatically in dark mode.
Motion
| Token | Default |
|---|---|
--bx-duration-fast |
120ms |
--bx-duration-base |
200ms |
--bx-duration-slow |
400ms |
--bx-easing-base |
cubic-bezier(0.4, 0, 0.2, 1) |
--bx-easing-bounce |
cubic-bezier(0.68, -0.55, 0.265, 1.55) |
Z-index
| Token | Default | Layer |
|---|---|---|
--bx-z-base |
1 |
Baseline |
--bx-z-dropdown |
100 |
Dropdowns |
--bx-z-sticky-header |
999 |
Sticky header |
--bx-z-overlay |
9999 |
Overlays / modals |
--bx-z-loader |
999991 |
Page loader |
--bx-z-toast |
999999 |
Toasts / notices |
Light and dark mode
The same token names power both modes. build_token_css() prints the light values into :root { … } and the dark values into :root[data-bx-mode="dark"] { … } from $dark_defaults. Because your CSS references only the token name, a mode swap is a single variable change, never a stylesheet swap.
:root { --bx-color-bg: #f7f7f9; --bx-color-fg: #505050; }
:root[data-bx-mode="dark"] { --bx-color-bg: #0a0a0a; --bx-color-fg: #f5f5f5; }
How the mode is chosen:
- The customizer field
site_color_modesets the site default (lightordark). Theauto/ system option was retired in 5.1.4; a legacy savedautoresolves tolight. - An inline bootstrap script (
emit_mode_script(), printed atwp_headpriority 1) stampsdata-bx-modeon<html>before first paint, reading the visitor's saved choice fromlocalStorage['bx-color-mode']and falling back to the site default. This prevents a flash of the wrong mode. - A dark style variation forces the dark default; a visitor can still toggle to light.
If you add custom colors, define both modes so your UI does not break under the dark cascade:
:root {
--my-plugin-panel-bg: var(--bx-color-bg-elevated);
--my-plugin-panel-fg: var(--bx-color-fg);
}
/* No override needed - the referenced tokens already flip in dark mode. */
Only hard-code a dark override when your value does not map to an existing token:
:root[data-bx-mode="dark"] {
--my-plugin-custom-glow: rgba(255, 107, 107, 0.25);
}
Overriding tokens in a child theme
Tokens are plain CSS custom properties, so a child theme overrides them with ordinary CSS specificity. Because the theme prints its token block as an inline style attached to the buddyx-global stylesheet, enqueue your child stylesheet as a dependent of that handle so your :root rule loads afterward and wins.
functions.php in your child theme:
add_action( 'wp_enqueue_scripts', function () {
wp_enqueue_style(
'buddyx-child',
get_stylesheet_directory_uri() . '/style.css',
array( 'buddyx-global' ), // Load after BuddyX tokens.
wp_get_theme()->get( 'Version' )
);
}, 20 );
style.css in your child theme:
:root {
--bx-color-accent: #6d28d9; /* Brand purple */
--bx-color-link: #6d28d9;
--bx-radius-card: 20px;
--bx-space-card: 32px;
}
/* Keep dark mode intentional - override there too when the value is fixed. */
:root[data-bx-mode="dark"] {
--bx-color-accent: #a78bfa;
}
Guidance:
- Prefer the customizer for anything a site owner should control (colors, radii, typography colors). Reach for a child-theme
:rootoverride only for values with no customizer field, or to lock a brand value regardless of customizer state. - Override at
:root, not on individual elements, so every consumer that references the token inherits your value. - To override a color for dark mode only, target
:root[data-bx-mode="dark"]. - Template overrides work the standard WordPress way. BuddyX loads its parts with
get_template_part(), so copying a template-part file into your child theme at the same relative path replaces it. Tokens are unaffected by template overrides.
Legacy aliases
Through the 5.2.x line, every canonical token also emits a legacy alias (for example --color-theme-primary, --global-border-radius, --color-footer-link) so pre-token stylesheets and third-party CSS keep working. Aliases are printed as --legacy: var(--bx-token);, so they flip light/dark through the canonical token automatically.
:root {
--bx-color-accent: #ef5455; /* Canonical - use this. */
--color-theme-primary: var(--bx-color-accent); /* Legacy alias. */
}
The alias maps live in $simple_color_tokens, $typography_color_tokens, $dimension_tokens, and $legacy_aliases in inc/Tokens/Component.php. Aliases are deprecated and slated for removal in 5.3.0. Migrate any consumers to the --bx-* names before then.
Reading tokens in PHP
Usually CSS is the right consumer. When you need the underlying value in PHP, read the customizer setting directly:
$accent = get_theme_mod( 'site_primary_color', '#ef5455' );
Or iterate the token map:
$tokens = \BuddyX\Buddyx\Tokens\Component::get_simple_color_tokens();
foreach ( $tokens as $mod_key => $cfg ) {
echo $cfg['token']; // e.g. '--bx-color-accent'
echo $cfg['aliases'][0]; // e.g. '--color-theme-primary'
}
You can force the dark-scheme decision for a custom style variation with the buddyx_variation_is_dark_scheme filter (receives the variation slug as its second argument).
Related
- Developer docs home
- Action hooks
- Filter hooks
- Assets and the manifest
- Child theme development