Universal CSS Theme Editor with Live Preview
Pick a theme. Customize colors. Export CSS. Zero dependencies.
Features • Quick Start • Themes • API • i18n • Full Guide
Pantinal is a drop-in CSS theme editor for any web project. It provides a unique Theme Shuttle -- a dropdown selector where every option shows a live miniature preview of your UI in that color scheme, before you select it. Plus a visual color editor with instant live preview.
No frameworks. No build step. No dependencies. Just one JS file.
npm install pantinal
Theme Shuttle -- A dropdown where each option renders a real-time mini-preview of your UI in that theme. You see how it looks before you commit. Nothing like this exists.
8 Built-in Themes -- 4 dark (Copper, Indigo, Emerald, Rose), 1 glass (Glassmorphism), 3 light (Clean, Arctic, Sand). All professionally designed with proper contrast ratios.
Visual Color Editor -- Click any color to customize. Changes apply instantly. When you're happy, export.
One-Click Export -- Export your theme as CSS Custom Properties or JSON. Copy to clipboard, paste into your project. Done.
i18n Ready -- Built-in English and German. Add any language with a simple JSON object.
Zero Dependencies -- One file. 15 KB gzipped. Works everywhere: React, Vue, Svelte, Astro, plain HTML. If it runs CSS Custom Properties, Pantinal works.
Framework Agnostic -- Pantinal generates standard CSS. Your framework doesn't matter.
<script src="pantinal.js"></script>
<div id="my-themes"></div>
<script>
const editor = new Pantinal(document.getElementById('my-themes'), {
theme: 'dark-copper',
locale: 'en'
});
</script>import { Pantinal } from './pantinal.js';
const editor = new Pantinal(document.querySelector('#themes'), {
theme: 'light-arctic',
locale: 'de',
onThemeChange: (theme) => {
console.log('Theme changed to:', theme.id);
}
});npm install pantinalimport { Pantinal } from 'pantinal';
const editor = new Pantinal(container, { theme: 'dark-indigo' });Pantinal themes use the --pn- prefix. Apply a theme with data-theme on any element:
[data-theme="dark-copper"] {
--pn-bg: #08080f;
--pn-surface: #101018;
--pn-text: #ececf4;
--pn-accent: #d4915e;
/* ... 20+ variables */
}Then use them in your CSS:
body {
background: var(--pn-bg);
color: var(--pn-text);
}
.card {
background: var(--pn-surface);
border: 1px solid var(--pn-border);
border-radius: var(--pn-radius);
}
.button {
background: var(--pn-accent);
color: var(--pn-accent-text);
}| Variable | Description |
|---|---|
--pn-bg |
Page background |
--pn-surface |
Card/panel background |
--pn-surface-2 |
Elevated surface |
--pn-surface-3 |
Highest elevation |
--pn-border |
Default border color |
--pn-border-hover |
Border on hover |
--pn-text |
Primary text |
--pn-text-dim |
Secondary text |
--pn-text-muted |
Tertiary/hint text |
--pn-accent |
Primary accent color |
--pn-accent-bright |
Bright accent variant |
--pn-accent-dim |
Subtle accent background |
--pn-accent-glow |
Glow/shadow accent |
--pn-accent-text |
Text on accent background |
--pn-secondary |
Secondary color |
--pn-secondary-dim |
Subtle secondary bg |
--pn-green |
Success color |
--pn-yellow |
Warning color |
--pn-red |
Error/danger color |
--pn-shadow |
Box shadow color |
--pn-radius |
Default border radius |
const editor = new Pantinal(container, options);Options:
| Option | Type | Default | Description |
|---|---|---|---|
theme |
string |
'dark-copper' |
Initial theme ID |
locale |
string |
'en' |
UI language ('en', 'de', or custom) |
target |
string|Element |
document.documentElement |
Element to apply data-theme to |
onThemeChange |
function |
null |
Callback when theme changes |
showEditor |
boolean |
true |
Show the color editor panel |
showExport |
boolean |
true |
Show export buttons |
persist |
boolean|string |
false |
Save to localStorage (true = 'pantinal-theme') |
editor.setTheme('dark-indigo'); // Switch theme
editor.getTheme(); // Get current theme object
editor.exportCSS('[data-theme]'); // Export as CSS string
editor.exportJSON(); // Export as JSON string
editor.addTheme({ id, name, ... }); // Register custom theme
editor.setLocale('de'); // Change language
editor.destroy(); // Remove and cleanupconst editor = new Pantinal(el, {
onThemeChange: (theme) => {
// theme = { id, name, category, vars: { ... } }
console.log('Now using:', theme.name.en);
}
});editor.addTheme({
id: 'my-brand',
name: { en: 'My Brand', de: 'Meine Marke' },
description: { en: 'Company colors', de: 'Firmenfarben' },
category: 'dark',
vars: {
'--pn-bg': '#0a0a12',
'--pn-surface': '#12121e',
'--pn-accent': '#ff6b2b',
// ... all variables
}
});Built-in languages: English (en), German (de).
Add your own:
const editor = new Pantinal(el, { locale: 'fr' });
editor.addLocale('fr', {
'shuttle.title': 'Themes',
'shuttle.dark': 'Sombre',
'shuttle.light': 'Clair',
'editor.customize': 'Personnaliser',
'editor.background': 'Arriere-plan',
'editor.surface': 'Surface',
'editor.text': 'Texte',
'editor.accent': 'Accent',
'editor.secondary': 'Secondaire',
'editor.reset': 'Reinitialiser',
'export.title': 'Exporter',
'export.css': 'Copier CSS',
'export.json': 'Copier JSON',
'export.copied': 'Copie!'
});Works in all modern browsers (Chrome, Firefox, Safari, Edge). Requires CSS Custom Properties support (96%+ global coverage).
Pantinal was born from the design work on PluriKey, an open-source password manager. While creating 8 themes for PluriKey, we realized the theme switcher with its unique live-preview dropdown was universally useful -- not just for password managers, but for any web project that uses CSS Custom Properties.
So we extracted it, polished it, made it framework-agnostic, and here it is.
The name? Pantone + Patina + Terminal = Pantinal. Color. Surface. Tech.
Pull requests welcome! Please keep the zero-dependency philosophy.
# Clone
git clone https://github.com/stlas/pantinal.git
cd pantinal
# Run local dev server
python3 -m http.server 8090
# or
npx serve .
# Open http://localhost:8090MIT -- Made with care by SANDY & the RASSELBANDE.