Plumeria logoPlumeria
API ReferenceJavaScript API

css.createTheme

type CreateTheme = {
  [key: string]: {
    default: string | number;
    theme: string | number;
  };
};

export type createTheme = <const T extends CreateTheme>(themeSelector: CreateThemeSelector, rule: T) => CreateThemeReturnType<T>;
export const createTheme: createTheme;

createTheme defines scoped, dynamic CSS variables for custom themes.
Since a unique hash is automatically prepended to the generated variable names, there is zero risk of name collisions with other themes or global CSS variables.


selector Patterns & Compiled CSS

createTheme supports class names, attribute selectors, and nesting-capable conditional at-rules (like @media, @container, @layer, @scope and @supports). Here are three common selector patterns and their compiled native CSS outputs:

1. Class-based Selector (.dark)

Excellent for toggling themes by adding a class to the root element.

import * as css from '@plumeria/core';

export const theme = css.createTheme('.dark', {
  text: {
    default: '#333',
    theme: '#eaeaea',
  },
});

Compiled CSS:

:where(:root) {
  --xkktl0fl-text: #333;
}

.dark {
  --xkktl0fl-text: #eaeaea;
}

2. Attribute-based Selector ([data-theme="dark"])

Great for attribute-based theme setups (e.g. Next-Themes).

import * as css from '@plumeria/core';

export const theme = css.createTheme('[data-theme="dark"]', {
  text: {
    default: '#333',
    theme: '#eaeaea',
  },
});

Compiled CSS:

:where(:root) {
  --xkktl0fl-text: #333;
}

[data-theme="dark"] {
  --xkktl0fl-text: #eaeaea;
}

3. Media Query (@media (prefers-color-scheme: dark))

Ideal for automatic system-level dark mode switching without any JavaScript.

import * as css from '@plumeria/core';

export const theme = css.createTheme('@media (prefers-color-scheme: dark)', {
  text: {
    default: '#333',
    theme: '#eaeaea',
  },
});

Compiled CSS:

:where(:root) {
  --xkktl0fl-text: #333;
}

@media (prefers-color-scheme: dark) {
  :where(:root) {
    --xkktl0fl-text: #eaeaea;
  }
}

Good to know

All APIs, including createTheme, are not compiled until the theme variable is actually used in a styling block.

On this page