CSS Theming
The Experience SDK uses CSS custom properties (variables) for comprehensive theming. All layout plugins (Banner, Modal, Inline) support full visual customization without overriding styles.
Quick Start
Override CSS variables in your stylesheet:
:root {
/* Brand colors */
--xp-modal-button-primary-bg: #8b5cf6; /* Purple */
--xp-banner-bg: #1f2937; /* Dark gray */
--xp-inline-button-primary-bg: #0ea5e9; /* Sky blue */
}All changes apply automatically to all experiences.
Banner Variables
Container & Layout
:root {
--xp-banner-z-index: 10000;
--xp-banner-padding: 16px 20px;
--xp-banner-gap: 16px; /* Space between elements */
}Colors & Backgrounds
:root {
/* Background */
--xp-banner-bg: #ffffff;
--xp-banner-border: 1px solid #e5e7eb;
--xp-banner-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
/* Text */
--xp-banner-title-color: #111827;
--xp-banner-message-color: #374151;
/* Close button */
--xp-banner-close-color: #6b7280;
--xp-banner-close-hover-color: #111827;
}Typography
:root {
--xp-banner-title-font-size: 16px;
--xp-banner-title-font-weight: 600;
--xp-banner-title-margin-bottom: 4px;
--xp-banner-message-font-size: 14px;
--xp-banner-message-line-height: 1.5;
}Buttons
:root {
/* Primary button */
--xp-banner-button-primary-bg: #2563eb;
--xp-banner-button-primary-color: #ffffff;
--xp-banner-button-primary-hover-bg: #1d4ed8;
/* Secondary button */
--xp-banner-button-secondary-bg: #f3f4f6;
--xp-banner-button-secondary-color: #374151;
--xp-banner-button-secondary-hover-bg: #e5e7eb;
--xp-banner-button-secondary-border: 1px solid #e5e7eb;
/* Link button */
--xp-banner-button-link-color: #2563eb;
--xp-banner-button-link-hover-bg: #f3f4f6;
/* Size */
--xp-banner-button-padding: 8px 16px;
--xp-banner-button-font-size: 14px;
--xp-banner-button-font-weight: 500;
--xp-banner-button-border-radius: 6px;
--xp-banner-buttons-gap: 8px;
}Modal Variables
Container & Backdrop
:root {
--xp-modal-z-index: 10001;
--xp-modal-backdrop-bg: rgba(0, 0, 0, 0.5);
}Dialog
:root {
--xp-modal-dialog-bg: #ffffff;
--xp-modal-dialog-border-radius: 8px;
--xp-modal-dialog-box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
--xp-modal-dialog-padding: 24px;
}Content
:root {
/* Title */
--xp-modal-title-font-size: 20px;
--xp-modal-title-font-weight: 600;
--xp-modal-title-color: #111;
--xp-modal-title-margin-bottom: 16px;
/* Message */
--xp-modal-message-font-size: 14px;
--xp-modal-message-line-height: 1.5;
--xp-modal-message-color: #444;
--xp-modal-message-margin-bottom: 20px;
/* Close button */
--xp-modal-close-color: #666;
--xp-modal-close-hover-color: #111;
}Buttons
:root {
/* Primary button */
--xp-modal-button-primary-bg: #2563eb;
--xp-modal-button-primary-color: #ffffff;
--xp-modal-button-primary-hover-bg: #1d4ed8;
/* Secondary button */
--xp-modal-button-secondary-bg: #f3f4f6;
--xp-modal-button-secondary-color: #374151;
--xp-modal-button-secondary-hover-bg: #e5e7eb;
--xp-modal-button-secondary-border-color: #e5e7eb;
/* Link button */
--xp-modal-button-link-color: #2563eb;
--xp-modal-button-link-hover-bg: #f3f4f6;
/* Size */
--xp-modal-button-padding: 10px 20px;
--xp-modal-button-font-size: 14px;
--xp-modal-button-font-weight: 500;
--xp-modal-button-border-radius: 6px;
--xp-modal-buttons-gap: 8px;
}Forms
:root {
/* Form container */
--xp-form-gap: 16px;
--xp-form-field-gap: 8px;
/* Label */
--xp-form-label-font-size: 14px;
--xp-form-label-font-weight: 500;
--xp-form-label-color: #1f2937;
--xp-form-required-color: #ef4444;
/* Input fields */
--xp-input-bg: #ffffff;
--xp-input-border-color: #d1d5db;
--xp-input-border-radius: 6px;
--xp-input-padding: 10px 12px;
--xp-input-font-size: 14px;
--xp-input-color: #1f2937;
--xp-input-placeholder-color: #6b7280;
/* Focus state */
--xp-input-focus-border-color: #2563eb;
--xp-input-focus-ring-color: rgba(59, 130, 246, 0.25);
/* Error state */
--xp-input-error-border-color: #ef4444;
--xp-input-error-focus-border-color: #dc2626;
--xp-input-error-focus-ring-color: rgba(239, 68, 68, 0.25);
--xp-error-message-color: #ef4444;
--xp-error-message-font-size: 12px;
/* Submit button */
--xp-submit-button-bg-primary: #2563eb;
--xp-submit-button-color-primary: #ffffff;
--xp-submit-button-hover-bg-primary: #1d4ed8;
--xp-submit-button-loading-bg: #e5e7eb;
--xp-submit-button-loading-color: #6b7280;
/* Success/error states */
--xp-form-state-success-bg: #ecfdf5;
--xp-form-state-success-border: 1px solid #a7f3d0;
--xp-form-state-success-color: #065f46;
--xp-form-state-error-bg: #fef2f2;
--xp-form-state-error-border: 1px solid #fca5a5;
--xp-form-state-error-color: #991b1b;
}Inline Variables
Close Button
:root {
--xp-inline-close-color: #666;
--xp-inline-close-hover-color: #111;
--xp-inline-close-size: 32px;
--xp-inline-close-bg: transparent;
--xp-inline-close-hover-bg: rgba(0, 0, 0, 0.1);
--xp-inline-close-border-radius: 4px;
}Buttons
:root {
/* Primary button */
--xp-inline-button-primary-bg: #2563eb;
--xp-inline-button-primary-color: #ffffff;
--xp-inline-button-primary-hover-bg: #1d4ed8;
/* Secondary button */
--xp-inline-button-secondary-bg: #f3f4f6;
--xp-inline-button-secondary-color: #374151;
--xp-inline-button-secondary-hover-bg: #e5e7eb;
--xp-inline-button-secondary-border-color: #e5e7eb;
/* Link button */
--xp-inline-button-link-color: #2563eb;
--xp-inline-button-link-hover-bg: #f3f4f6;
/* Size */
--xp-inline-button-padding: 8px 16px;
--xp-inline-button-font-size: 14px;
--xp-inline-button-font-weight: 500;
--xp-inline-button-border-radius: 4px;
--xp-inline-buttons-gap: 8px;
}Dark Mode
All plugins include automatic dark mode support using prefers-color-scheme:
@media (prefers-color-scheme: dark) {
:root {
/* Banner */
--xp-banner-bg: #1f2937;
--xp-banner-title-color: #f9fafb;
--xp-banner-message-color: #d1d5db;
/* Modal */
--xp-modal-backdrop-bg: rgba(0, 0, 0, 0.7);
--xp-modal-dialog-bg: #1f2937;
--xp-modal-title-color: #f9fafb;
--xp-modal-message-color: #d1d5db;
/* Forms */
--xp-input-bg: #1f2937;
--xp-input-border-color: #374151;
--xp-input-color: #f9fafb;
/* Buttons */
--xp-modal-button-primary-bg: #3b82f6;
--xp-modal-button-secondary-bg: #374151;
--xp-modal-button-secondary-color: #f9fafb;
}
}Complete Examples
Brand Colors
:root {
/* Apply your brand colors across all experiences */
--xp-banner-button-primary-bg: #8b5cf6; /* Purple */
--xp-modal-button-primary-bg: #8b5cf6;
--xp-inline-button-primary-bg: #8b5cf6;
--xp-banner-button-primary-hover-bg: #7c3aed;
--xp-modal-button-primary-hover-bg: #7c3aed;
--xp-inline-button-primary-hover-bg: #7c3aed;
}E-Commerce Theme
:root {
/* High-contrast, conversion-focused */
--xp-banner-bg: #000000;
--xp-banner-title-color: #ffffff;
--xp-banner-message-color: #d1d5db;
--xp-banner-button-primary-bg: #ef4444; /* Red CTA */
--xp-banner-button-primary-color: #ffffff;
--xp-banner-button-primary-hover-bg: #dc2626;
--xp-banner-button-secondary-bg: transparent;
--xp-banner-button-secondary-color: #ffffff;
--xp-banner-button-secondary-border: 1px solid #ffffff;
--xp-banner-button-secondary-hover-bg: rgba(255, 255, 255, 0.1);
}SaaS Theme
:root {
/* Clean, professional */
--xp-modal-dialog-border-radius: 12px;
--xp-modal-dialog-padding: 32px;
--xp-modal-dialog-box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
--xp-modal-button-primary-bg: #0ea5e9; /* Sky blue */
--xp-modal-button-primary-hover-bg: #0284c7;
--xp-modal-button-border-radius: 8px;
--xp-input-border-radius: 8px;
--xp-input-padding: 12px 16px;
--xp-input-focus-border-color: #0ea5e9;
--xp-input-focus-ring-color: rgba(14, 165, 233, 0.25);
}Minimalist Theme
:root {
/* Subtle, understated */
--xp-banner-bg: #fafafa;
--xp-banner-border: none;
--xp-banner-shadow: none;
--xp-banner-padding: 12px 16px;
--xp-banner-title-font-size: 14px;
--xp-banner-message-font-size: 13px;
--xp-banner-button-primary-bg: #171717;
--xp-banner-button-primary-color: #ffffff;
--xp-banner-button-secondary-bg: transparent;
--xp-banner-button-secondary-color: #171717;
--xp-banner-button-border-radius: 4px;
}Per-Experience Customization
For experience-specific styling, use className or style props:
Using className
experiences.register('sale', {
type: 'modal',
content: {
title: 'Flash Sale!',
message: '24 hours only.',
className: 'sale-modal', // Custom class
buttons: [...]
}
});/* Your CSS */
.sale-modal {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.sale-modal .xp-modal__title {
font-size: 32px;
text-transform: uppercase;
}Using Inline Styles
{
content: {
message: 'Limited offer',
style: {
background: '#fef3c7',
border: '2px solid #f59e0b',
borderRadius: '12px'
}
}
}CSS Class Reference
Banner
.xp-banner- Container.xp-banner__close- Close button.xp-banner__title- Title text.xp-banner__message- Message text.xp-banner__buttons- Button container.xp-banner__button- Individual button.xp-banner__button--primary- Primary variant.xp-banner__button--secondary- Secondary variant.xp-banner__button--link- Link variant
Modal
.xp-modal- Container.xp-modal__backdrop- Backdrop overlay.xp-modal__dialog- Dialog box.xp-modal__close- Close button.xp-modal__hero-image- Hero image (if present).xp-modal__content- Content wrapper.xp-modal__title- Title text.xp-modal__message- Message text.xp-modal__buttons- Button container.xp-modal__button- Individual button.xp-modal__form- Form container.xp-form__field- Form field wrapper.xp-form__label- Field label.xp-form__input- Input field.xp-form__error- Error message.xp-form__submit- Submit button
Inline
.xp-inline- Container.xp-inline__close- Close button.xp-inline__buttons- Button container.xp-inline__button- Individual button
Integration with Frameworks
Tailwind CSS
{
content: {
message: 'Flash Sale!',
className: 'bg-gradient-to-r from-purple-600 to-pink-600 text-white shadow-2xl',
buttons: [{
text: 'Shop Now',
className: 'bg-white text-purple-600 hover:bg-gray-100 font-bold'
}]
}
}CSS Modules
import styles from './experiences.module.css';
{
content: {
message: 'Special offer',
className: styles.promo,
buttons: [{
text: 'Learn More',
className: styles.button
}]
}
}Styled Components
import { createGlobalStyle } from 'styled-components';
const GlobalStyles = createGlobalStyle`
:root {
--xp-modal-button-primary-bg: ${props => props.theme.colors.primary};
--xp-banner-bg: ${props => props.theme.colors.surface};
}
`;Best Practices
- Define once, apply everywhere - Set global CSS variables for consistent branding
- Use semantic naming - CSS variables describe purpose, not appearance
- Support dark mode - Include
prefers-color-schemeoverrides - Test responsively - Some variables affect mobile differently
- Progressive enhancement - Styles gracefully degrade if variables unsupported
- Avoid
!important- CSS variables have high specificity already
Browser Support
CSS custom properties are supported in:
- Chrome 49+
- Firefox 31+
- Safari 9.1+
- Edge 15+
- iOS Safari 9.3+
- Chrome Android 49+
For older browsers, fallback values are automatically applied.
Next Steps
- Banner Plugin - Banner-specific examples
- Modal Plugin - Modal-specific examples
- Inline Plugin - Inline-specific examples
- Events - Listen to experience events