Customizing Themes
Make PACE.js match your brand with custom themes.
Default Theme
PACE.js ships with a purple gradient theme inspired by MillPond:
css
:root {
--pace-primary: #667eea;
--pace-accent: #764ba2;
--pace-bg: #ffffff;
--pace-text: #1a1a1a;
--pace-font: Inter, system-ui, sans-serif;
}CSS Custom Properties
All styling uses CSS custom properties (variables) for easy theming.
Complete Variable List
css
:root {
/* Colors */
--pace-primary: #667eea;
--pace-accent: #764ba2;
--pace-bg: #ffffff;
--pace-bg-soft: #f9f9f9;
--pace-bg-mute: #f1f1f1;
--pace-text: #1a1a1a;
--pace-text-secondary: #666666;
--pace-text-muted: #999999;
--pace-border: #e0e0e0;
/* Typography */
--pace-font: Inter, system-ui, sans-serif;
--pace-font-mono: 'Fira Code', monospace;
--pace-font-size-base: 16px;
--pace-line-height: 1.6;
/* Spacing */
--pace-spacing-xs: 0.25rem;
--pace-spacing-sm: 0.5rem;
--pace-spacing-md: 1rem;
--pace-spacing-lg: 1.5rem;
--pace-spacing-xl: 2rem;
/* Border Radius */
--pace-radius-sm: 4px;
--pace-radius-md: 8px;
--pace-radius-lg: 12px;
/* Shadows */
--pace-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);
--pace-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.1);
--pace-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.15);
/* Transitions */
--pace-transition-fast: 150ms ease;
--pace-transition-base: 250ms ease;
--pace-transition-slow: 350ms ease;
/* Z-index */
--pace-z-sidebar: 100;
--pace-z-modal: 1000;
--pace-z-tooltip: 2000;
}Option 1: CSS Override
Override variables in your own stylesheet:
css
/* custom-theme.css */
:root {
--pace-primary: #3b82f6; /* Blue */
--pace-accent: #8b5cf6; /* Purple */
--pace-font: 'Roboto', sans-serif;
}html
<link rel="stylesheet" href="pace.min.css">
<link rel="stylesheet" href="custom-theme.css">Option 2: JavaScript Configuration
Pass theme config to PACE constructor:
javascript
const pace = new PACE({
container: '#app',
products: './products.json',
theme: {
primary: '#3b82f6',
accent: '#8b5cf6',
font: 'Roboto, sans-serif',
background: '#f8fafc',
text: '#0f172a'
}
})Pre-built Themes
Blue Ocean
css
:root {
--pace-primary: #0ea5e9;
--pace-accent: #06b6d4;
--pace-bg: #f0f9ff;
--pace-text: #0c4a6e;
}Green Forest
css
:root {
--pace-primary: #10b981;
--pace-accent: #059669;
--pace-bg: #f0fdf4;
--pace-text: #064e3b;
}Orange Sunset
css
:root {
--pace-primary: #f97316;
--pace-accent: #ea580c;
--pace-bg: #fff7ed;
--pace-text: #7c2d12;
}Monochrome
css
:root {
--pace-primary: #18181b;
--pace-accent: #3f3f46;
--pace-bg: #ffffff;
--pace-text: #09090b;
}Dark Mode
Automatic Dark Mode
css
.dark {
--pace-primary: #a78bfa;
--pace-accent: #c4b5fd;
--pace-bg: #1a1a2e;
--pace-bg-soft: #252538;
--pace-text: #ffffff;
--pace-text-secondary: #d1d5db;
--pace-border: #374151;
}Toggle Implementation
javascript
// Dark mode toggle
const toggleDarkMode = () => {
document.documentElement.classList.toggle('dark')
localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light')
}
// Persist preference
const savedTheme = localStorage.getItem('theme')
if (savedTheme === 'dark') {
document.documentElement.classList.add('dark')
}
// System preference
if (window.matchMedia('(prefers-color-scheme: dark)').matches && !savedTheme) {
document.documentElement.classList.add('dark')
}Component-Specific Styling
Product Cards
css
.pace-product-card {
border-left: 4px solid var(--pace-primary);
background: linear-gradient(135deg, #ffffff 0%, #f9fafb 100%);
}
.pace-product-card:hover {
transform: translateY(-4px);
box-shadow: var(--pace-shadow-lg);
}
.pace-product-card h3 {
color: var(--pace-primary);
font-weight: 600;
}Chat Messages
css
.pace-chat-message.user {
background: var(--pace-primary);
color: white;
border-radius: 1rem 1rem 0 1rem;
}
.pace-chat-message.assistant {
background: var(--pace-bg-soft);
color: var(--pace-text);
border-radius: 1rem 1rem 1rem 0;
border-left: 3px solid var(--pace-accent);
}Navigation
css
.pace-nav-item {
transition: all var(--pace-transition-base);
}
.pace-nav-item:hover {
background: var(--pace-bg-soft);
border-left: 4px solid var(--pace-primary);
}
.pace-nav-item.active {
background: linear-gradient(135deg, var(--pace-primary), var(--pace-accent));
color: white;
}Brand Integration
Match Your Existing Site
css
/* Extract colors from your brand */
:root {
--pace-primary: var(--brand-primary, #667eea);
--pace-accent: var(--brand-accent, #764ba2);
--pace-font: var(--brand-font, Inter);
}
/* Use your existing design tokens */
.pace-container {
font-family: var(--pace-font);
color: var(--pace-text);
}Advanced Customization
Gradient Backgrounds
css
.pace-sidebar {
background: linear-gradient(
180deg,
var(--pace-primary) 0%,
var(--pace-accent) 100%
);
}
.pace-product-card {
background: linear-gradient(
135deg,
rgba(102, 126, 234, 0.05) 0%,
rgba(118, 75, 162, 0.05) 100%
);
}Animations
css
@keyframes slideIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.pace-product-card {
animation: slideIn var(--pace-transition-base);
}
.pace-chat-message {
animation: slideIn 0.2s ease-out;
}Custom Fonts
css
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap');
:root {
--pace-font: 'Poppins', sans-serif;
}
h1, h2, h3 {
font-weight: 700;
letter-spacing: -0.02em;
}Responsive Design
PACE.js is mobile-friendly by default, but you can customize breakpoints:
css
/* Mobile */
@media (max-width: 768px) {
.pace-sidebar {
width: 100%;
height: auto;
position: static;
}
.pace-product-grid {
grid-template-columns: 1fr;
}
}
/* Tablet */
@media (min-width: 769px) and (max-width: 1024px) {
.pace-product-grid {
grid-template-columns: repeat(2, 1fr);
}
}
/* Desktop */
@media (min-width: 1025px) {
.pace-product-grid {
grid-template-columns: repeat(3, 1fr);
}
}Best Practices
1. Use Variables, Not Hard-Coded Colors
✅ Good:
css
.custom-element {
color: var(--pace-primary);
}❌ Bad:
css
.custom-element {
color: #667eea;
}2. Test Dark Mode
Always test your custom theme in both light and dark modes.
3. Maintain Contrast
Ensure text meets WCAG AA standards (4.5:1 ratio):
css
/* Good contrast */
:root {
--pace-bg: #ffffff;
--pace-text: #1a1a1a; /* 16:1 ratio */
}
/* Poor contrast */
:root {
--pace-bg: #f5f5f5;
--pace-text: #999999; /* 2.8:1 ratio - too low! */
}4. Use System Fonts for Performance
css
:root {
--pace-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}Complete Theme Example
css
/* custom-theme.css */
/* Brand colors */
:root {
--pace-primary: #3b82f6;
--pace-accent: #8b5cf6;
--pace-bg: #f8fafc;
--pace-text: #0f172a;
--pace-font: 'Inter', system-ui, sans-serif;
}
/* Dark mode */
.dark {
--pace-primary: #60a5fa;
--pace-accent: #a78bfa;
--pace-bg: #0f172a;
--pace-text: #f1f5f9;
}
/* Product cards */
.pace-product-card {
border-radius: 12px;
border: 1px solid #e2e8f0;
transition: all 0.2s;
}
.pace-product-card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 24px rgba(59, 130, 246, 0.15);
border-color: var(--pace-primary);
}
/* Chat messages */
.pace-chat-message.user {
background: linear-gradient(135deg, #3b82f6, #8b5cf6);
color: white;
border-radius: 1rem 1rem 0.25rem 1rem;
}
.pace-chat-message.assistant {
background: white;
border: 1px solid #e2e8f0;
border-radius: 1rem 1rem 1rem 0.25rem;
}
/* Navigation */
.pace-nav-item.active {
background: linear-gradient(90deg, var(--pace-primary), var(--pace-accent));
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
}
/* Animations */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.pace-product-card,
.pace-chat-message {
animation: fadeIn 0.3s ease-out;
}Make PACE.js yours with custom themes! 🎨