Skip to content

Variables

The core:variables plugin manages CSS custom properties (variables). It handles declaration output as preflight CSS, nested selectors for theming, autocomplete integration, and unused variable pruning.

How It Works

  1. Variable definitions are collected from config.variables.variables during rawConfigConfigured.
  2. During configureEngine, each variable is resolved and registered:
    • Autocomplete entries are added (e.g., var(--name) as a value suggestion).
    • Variables with values are stored in engine.variables.store.
  3. A preflight function scans all atomic styles for var(--name) patterns to determine which variables are actually used.
  4. Only used variables (plus safe-listed ones) are emitted to CSS output.

Config

ts
interface VariablesConfig {
  /** Variable definitions — a single object or an array of objects. */
  variables: VariablesDefinition | VariablesDefinition[]
  /** Whether to prune unused variables from CSS output. @default true */
  pruneUnused?: boolean
  /** Variables that are always included regardless of usage. @default [] */
  safeList?: `--${string}`[]
}

VariablesDefinition

A recursive object where:

  • Keys starting with -- define CSS variables.
  • Other keys are treated as CSS selectors for scoping.
  • Values can be a simple CSS value or a VariableObject for fine-grained control.

VariableObject

ts
interface VariableObject {
  value?: string | number | null
  autocomplete?: {
    /** Which CSS properties suggest var(--name). @default ['*'] */
    asValueOf?: string | string[]
    /** Register --name as a CSS property in autocomplete. @default true */
    asProperty?: boolean
  }
  /** Override pruning for this specific variable. */
  pruneUnused?: boolean
}

Basic Usage

Define variables in your pika.config.ts. Top-level variables are placed under :root by default:

ts
// pika.config.ts
import { defineEngineConfig } from '@pikacss/unplugin-pikacss'

export default defineEngineConfig({
	variables: {
		variables: {
			// Top-level variables are placed under :root
			'--color-primary': '#0ea5e9',
			'--color-bg': '#ffffff',
			'--color-text': '#1e293b',

			// Nest under a selector to scope variables
			'[data-theme="dark"]': {
				'--color-bg': '#0f172a',
				'--color-text': '#e2e8f0',
			},
		},
		// Prune variables not referenced in any atomic style (default: true)
		pruneUnused: true,
		// Always keep these variables even if unused
		safeList: ['--color-primary'],
	},
})

Use the variables in your styles:

ts
const className = pika({
	color: 'var(--color-text)',
	backgroundColor: 'var(--color-bg)',
})

Generated CSS output (preflight + atomic styles):

css
/* Preflight: variable declarations */
:root {
  --color-primary: #0ea5e9;
  --color-bg: #ffffff;
  --color-text: #1e293b;
}
[data-theme="dark"] {
  --color-bg: #0f172a;
  --color-text: #e2e8f0;
}

/* Atomic styles generated by pika() */
.a { color: var(--color-text); }
.b { background-color: var(--color-bg); }

Variable Object Form

Use an object value for fine-grained control over autocomplete and pruning:

ts
// pika.config.ts
import { defineEngineConfig } from '@pikacss/unplugin-pikacss'

export default defineEngineConfig({
	variables: {
		variables: {
			// Object form with autocomplete and pruning options
			'--color-primary': {
				value: '#0ea5e9',
				autocomplete: {
					// Suggest var(--color-primary) for these CSS properties
					// Use '*' for all properties, '-' to disable
					asValueOf: ['color', 'backgroundColor'],
					// Whether to register --color-primary as a CSS property (default: true)
					asProperty: true,
				},
				// Override per-variable pruning (default: inherits from config)
				pruneUnused: false,
			},

			// A variable with value null provides autocomplete only — no CSS output
			'--external-font-size': {
				value: null,
				autocomplete: {
					asValueOf: ['fontSize'],
				},
			},
		},
	},
})

Null-Value Variables

Variables with value: null provide autocomplete suggestions without emitting any CSS declaration. This is useful for variables defined externally (e.g., by a third-party stylesheet).

Unused Variable Pruning

By default, pruneUnused is true. A variable is kept in CSS output when any of the following is true:

  • It is referenced via var(--name) in an atomic style value
  • It appears in the safeList array
  • Its per-variable pruneUnused is explicitly set to false

Dynamic Variables via Engine API

Plugins can add variables programmatically at runtime:

ts
engine.variables.add({
  '--dynamic-color': '#ff007f',
})

The engine.variables.store is a Map<string, ResolvedVariable[]> holding all registered variables, keyed by variable name.

Behavior Summary

AspectDetail
Plugin namecore:variables
Default selector:root (for top-level variables)
pruneUnused defaulttrue
autocomplete.asValueOf default['*']
autocomplete.asProperty defaulttrue
Null-value variablesRegistered for autocomplete only, not emitted to CSS
DetectionScans atomic style values for var(--name) patterns

Source Reference

  • packages/core/src/internal/plugins/variables.ts

Next