Try it
Click a theme below, then look at the editor — it updates instantly using CSS variables, with no editor recreation.

Live Theme Switcher

Live Editor Preview

This CodeMirror editor uses CSS variables for all colors — switch themes above to see it change:

CodeMirror 6 — Theme: light

Color Palette (Current: light)

--color-bg
--color-text
--color-primary
--color-secondary
--color-surface
--color-border

CSS Variables Approach

css
:root {
  --color-bg: #ffffff;
  --color-text: #1a1a1a;
  --color-primary: #0066cc;
  --color-secondary: #6b7280;
  --color-border: #e5e7eb;
  --color-surface: #f3f4f6;
}

[data-theme="dark"] {
  --color-bg: #111827;
  --color-text: #f3f4f6;
  --color-primary: #60a5fa;
  --color-border: #374151;
  --color-surface: #1f2937;
}

/* Components use variables — no hardcoded colors */
.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  color: var(--color-text);
}

CodeMirror 6 Theming

By using CSS variables in CodeMirror's theme, the editor automatically reflects theme changes:

typescript
import { EditorView } from '@codemirror/view';

// CodeMirror theme using CSS variables
const myTheme = EditorView.theme({
  '&': {
    backgroundColor: 'var(--color-bg)',
    color: 'var(--color-text)'
  },
  '.cm-gutters': {
    backgroundColor: 'var(--color-surface)',
    borderRight: '1px solid var(--color-border)'
  },
  '&.cm-focused .cm-cursor': {
    borderLeftColor: 'var(--color-primary)'
  }
});
// Theme auto-updates when CSS variables change!

Theme Store

typescript
import { writable } from 'svelte/store';
import { browser } from '$app/environment';

export type ThemeName = 'light' | 'dark' | 'sepia' | 'high-contrast';

const stored = browser ? localStorage.getItem('theme') : null;
export const theme = writable<ThemeName>(stored || 'light');

if (browser) {
  theme.subscribe((t) => {
    localStorage.setItem('theme', t);
    document.documentElement.setAttribute('data-theme', t);
  });
}

Architecture

Chrome vs Content App UI and document content should be independently themeable
System preference Respect prefers-color-scheme media query
Persistence Save preference to localStorage
No runtime cost CSS variables update instantly, no re-renders needed
Composable Override individual variables for brand theming

Strengths (CSS Variables)

  • Zero runtime overhead
  • Works with any framework
  • Easy to compose and override
  • Works with CodeMirror, ProseMirror, etc.
  • No build step required

Weaknesses

  • No type safety for variable names
  • Can't compute derived values
  • Need to preset all values per theme