Custom Themes & Dark Mode
Consenti's entire visual layer is built on CSS custom properties. You can match it to your brand by overriding a handful of variables in your stylesheet — no build step, no Shadow DOM to pierce, no specificity battles.
How theming works
The widget reads CSS custom properties from the :root scope at render time. Override any --consenti-* token in your own stylesheet and the widget picks it up automatically. You can also pass a core.theme object to ConsentiSetup to set tokens via JavaScript — useful when your brand colours come from an API or theme context.
Option A — CSS custom property override
This is the recommended approach for static brand customisation. No CSS import is required —ConsentiSetup injects its own default <style> tag at runtime. Add your overrides in your own stylesheet, loaded normally in your page.
:root {
/* Primary button and active states */
--consenti-btn-primary-bg: #7c3aed;
--consenti-btn-primary-text: #ffffff;
/* Secondary button */
--consenti-btn-secondary-bg: #f5f0ff;
--consenti-btn-secondary-text: #7c3aed;
/* Banner background */
--consenti-primary-bg: #ffffff;
--consenti-primary-text: #1a1a2e;
/* Border radius — pill buttons */
--consenti-btn-radius: 999px;
--consenti-banner-radius: 12px;
--consenti-modal-radius: 16px;
/* Typography */
--consenti-font-family: 'Inter', system-ui, sans-serif;
--consenti-font-size-base: 14px;
/* Toggle colours */
--consenti-toggle-on: #7c3aed;
--consenti-toggle-off: #d1d5db;
}Option B — JS theme config
Pass a core.theme object to ConsentiSetup. The widget translates each field into the corresponding CSS custom property at initialisation.
new ConsentiSetup({
compliance: { type: 'opt-in' },
core: {
theme: {
primaryColor: '#7c3aed', // maps to --consenti-btn-primary-bg
primaryTextColor: '#ffffff',
secondaryColor: '#f5f0ff',
secondaryTextColor: '#7c3aed',
borderRadius: '12px',
buttonBorderRadius: '999px', // pill buttons
fontFamily: 'Inter, system-ui, sans-serif',
fontSizeBase: '14px',
bgColor: '#ffffff',
textColor: '#1a1a2e',
},
},
})Runtime theme swapping
Use widget.setTheme()to hot-swap tokens after the widget is initialised. This merges the new values into the current theme — you don't need to pass the full theme object.
const widget = new ConsentiSetup({ /* ... */ })
// Later — e.g. when a theme switcher is toggled
widget.setTheme({ primaryColor: '#e11d48' }) // swap accent colour onlyDark mode
Set darkMode: true in config, or let the widget follow the system preference:
// Follow system preference
new ConsentiSetup({
compliance: { type: 'opt-in' },
darkMode: window.matchMedia('(prefers-color-scheme: dark)').matches,
})
// Or toggle at runtime
widget.setDarkMode() // toggle
widget.setDarkMode(true) // force dark
widget.setDarkMode(false) // force lightwidget.setDarkMode(isDark) whenever your theme changes.Full CSS token reference
| Token | Default | What it controls |
|---|---|---|
| --consenti-primary-bg | #ffffff | Banner & modal background |
| --consenti-primary-text | #1a1a1a | Main text colour |
| --consenti-secondary-bg | #f5f5f5 | Secondary surfaces |
| --consenti-secondary-text | #555555 | Secondary text |
| --consenti-btn-primary-bg | #1565c0 | Primary button background |
| --consenti-btn-primary-text | #ffffff | Primary button text |
| --consenti-btn-secondary-bg | #f5f5f5 | Secondary button background |
| --consenti-btn-secondary-text | #1a3460 | Secondary button text |
| --consenti-btn-radius | 6px | Button border radius |
| --consenti-btn-padding | 0.5rem 1.25rem | Button padding |
| --consenti-banner-padding | 1.5rem | Banner inner padding |
| --consenti-banner-radius | 0 | Banner border radius |
| --consenti-banner-shadow | 0 -4px 24px rgba(0,0,0,.12) | Banner box shadow |
| --consenti-modal-width | 560px | Modal max width |
| --consenti-modal-radius | 12px | Modal border radius |
| --consenti-modal-shadow | 0 8px 32px rgba(0,0,0,.24) | Modal box shadow |
| --consenti-toggle-on | #1565c0 | Toggle on-state colour |
| --consenti-toggle-off | #ccc | Toggle off-state colour |
| --consenti-font-family | system-ui, sans-serif | Widget font family |
| --consenti-font-size-base | 14px | Base font size |