Skip to content

Configuration

PikaCSS configuration has two layers, and confusing them is one of the easiest ways to misread the system.

  1. Engine config controls how styles are understood and rendered.
  2. Build plugin options control how the integration finds, transforms, and generates files.

Engine config

Use engine config for things that change styling behavior:

  • plugins
  • autocomplete
  • selectors
  • shortcuts
  • variables
  • keyframes
  • layers
  • cssImports
  • preflights
  • prefix and selector defaults
ts
// pika.config.ts
import { defineEngineConfig } from '@pikacss/core'

export default defineEngineConfig({
	prefix: 'pika-',
	defaultSelector: '.%',
	preflights: [
		':root { --app-radius: 12px; }',
	],
	plugins: [],
})
ts
// pika.config.ts
import { defineEngineConfig } from '@pikacss/core'
import { fonts } from '@pikacss/plugin-fonts'
import { icons } from '@pikacss/plugin-icons'
import { reset } from '@pikacss/plugin-reset'

export default defineEngineConfig({
	plugins: [
		reset(),
		fonts(),
		icons(),
	],

	prefix: 'pk-',
	defaultSelector: '.%',

	autocomplete: {
		styleItemStrings: ['btn-primary'],
		properties: {
			variant: ['"solid"', '"ghost"'],
		},
		patterns: {
			selectors: ['screen-${number}'],
		},
	},

	cssImports: [
		'@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap");',
	],

	preflights: [
		'*, *::before, *::after { box-sizing: border-box; }',
	],

	fonts: {
		fonts: {
			sans: 'Roboto:400,700',
		},
	},

	important: {
		default: false,
	},

	variables: {
		variables: {
			'--color-bg': '#ffffff',
			'--color-text': '#1a1a1a',
			'[data-theme="dark"]': {
				'--color-bg': '#1a1a1a',
				'--color-text': '#ffffff',
			},
		},
		pruneUnused: true,
		safeList: ['--color-bg', '--color-text'],
	},

	keyframes: {
		keyframes: [
			['fade-in', {
				from: { opacity: '0' },
				to: { opacity: '1' },
			}, ['fade-in 0.3s ease']],
		],
		pruneUnused: true,
	},

	selectors: {
		selectors: [
			['hover', '$:hover'],
			['focus', '$:focus'],
			['dark', '[data-theme="dark"] $'],
		],
	},

	shortcuts: {
		shortcuts: [
			['flex-center', {
				display: 'flex',
				alignItems: 'center',
				justifyContent: 'center',
			}],
		],
	},
})

Custom autocomplete

Use autocomplete when your app or design system has stable custom style tokens that do not come from a plugin.

These entries are merged with built-in and external plugin autocomplete, then written into the generated TypeScript types.

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

export default defineEngineConfig({
	autocomplete: {
		styleItemStrings: ['btn-primary', 'btn-secondary'],
		extraProperties: ['variant'],
		properties: {
			variant: ['"solid"', '"ghost"'],
		},
		patterns: {
			selectors: ['screen-${number}'],
			styleItemStrings: ['icon-${string}'],
		},
	},
})

Semantic variable autocomplete

Use variables.*.semanticType when a CSS variable represents a stable value family and you want PikaCSS to attach var(--token) only to matching CSS property autocomplete.

Current built-in semantic families with runtime expansion are:

  • color
  • length
  • time
  • number
  • easing
  • font-family

semanticType expands to the built-in property set first, then unions with any explicit autocomplete.asValueOf entries you add for project-specific outliers.

ts
import { defineEngineConfig } from '@pikacss/core'

export default defineEngineConfig({
	variables: {
		variables: {
			// Built-in semantic families scope autocomplete to matching CSS properties.
			'--color-primary': {
				value: '#3b82f6',
				semanticType: 'color',
			},
			'--space-md': {
				value: '16px',
				semanticType: 'length',
			},
			'--motion-fast': {
				value: '120ms',
				semanticType: 'time',
			},
			'--layer-popover': {
				value: '20',
				semanticType: 'number',
			},
			'--ease-standard': {
				value: 'ease-in-out',
				semanticType: 'easing',
			},
			'--font-ui': {
				value: 'Inter, sans-serif',
				semanticType: 'font-family',
			},

			// Explicit autocomplete targets still union with semanticType expansion.
			'--brand-accent': {
				value: '#0ea5e9',
				semanticType: 'color',
				autocomplete: {
					asValueOf: 'scrollbar-color',
				},
			},
		},
		pruneUnused: false,
	},
})

Built-in plugins are configured by top-level keys

This is important because built-in plugin configuration does not live inside plugins.

ts
import { defineEngineConfig } from '@pikacss/core'

export default defineEngineConfig({
	important: { default: false },
	variables: { variables: {} },
	keyframes: { keyframes: [] },
	selectors: { selectors: [] },
	shortcuts: { shortcuts: [] },
})
Built-in capabilityWhere to configure it
variablesvariables
keyframeskeyframes
selectorsselectors
shortcutsshortcuts
importantimportant

External plugins go in plugins

ts
import { defineEngineConfig } from '@pikacss/core'
import { fonts } from '@pikacss/plugin-fonts'
import { icons } from '@pikacss/plugin-icons'
import { reset } from '@pikacss/plugin-reset'
import { typography } from '@pikacss/plugin-typography'

export default defineEngineConfig({
	plugins: [
		reset(),
		fonts(),
		icons(),
		typography(),
	],
	fonts: {
		fonts: {
			sans: 'Roboto:400,700',
		},
	},
})

Common misunderstanding

If you put official external plugins such as reset, fonts, icons, or typography under built-in config keys, nothing useful happens. Built-in plugin config and external plugin registration are two different mechanisms.

Build plugin options

Use build plugin options for integration behavior such as scanning, config path resolution, generated file locations, and function name detection.

ts
import type { PluginOptions } from '@pikacss/unplugin-pikacss'

// All options are optional — sensible defaults are provided
const options: PluginOptions = {
	// File patterns to scan for pika() calls
	scan: {
		include: ['**/*.{js,ts,jsx,tsx,vue}'], // default
		exclude: ['node_modules/**', 'dist/**'], // default
	},

	// Engine config: inline object or path to config file
	config: './pika.config.ts',

	// Auto-create a config file if none exists
	autoCreateConfig: true, // default

	// The function name to detect in source code
	fnName: 'pika', // default

	// Output format of generated class names
	// - 'string': "pk-a pk-b pk-c"
	// - 'array':  ['pk-a', 'pk-b', 'pk-c']
	transformedFormat: 'string', // default

	// TypeScript codegen file for autocomplete support
	// - true:   generates 'pika.gen.ts'
	// - string: custom file path
	// - false:  disable
	tsCodegen: true, // default → 'pika.gen.ts'

	// CSS codegen file containing all atomic styles
	// - true:   generates 'pika.gen.css'
	// - string: custom file path
	cssCodegen: true, // default → 'pika.gen.css'
}

Layers, CSS imports, preflights, and ordering

For larger systems, layer control matters because it makes output order intentional instead of accidental.

Use cssImports when you need top-level @import rules to stay ahead of layered preflights and generated utilities. This is the config-level equivalent of engine.appendCssImport().

ts
import { defineEngineConfig } from '@pikacss/core'

export default defineEngineConfig({
	// Add a 'components' layer between preflights and utilities
	layers: {
		base: 0,
		components: 5,
		utilities: 10,
	},
	// Unlayered preflights go into 'base' instead of the default 'preflights'
	defaultPreflightsLayer: 'base',
	// Unlayered atomic styles go into 'utilities' (this is the default)
	defaultUtilitiesLayer: 'utilities',
})
ts
import { defineEngineConfig } from '@pikacss/core'

export default defineEngineConfig({
	cssImports: [
		'@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap");',
		'@import url("https://cdn.example.com/theme.css");',
	],

	preflights: [
		':root { font-family: "Inter", system-ui, sans-serif; }',
	],
})
ts
import { defineEngineConfig } from '@pikacss/core'

export default defineEngineConfig({
	layers: {
		reset: 0,
		base: 1,
		utilities: 10,
	},
	preflights: [
		// WithLayer + CSS string
		{
			layer: 'reset',
			preflight: '*, *::before, *::after { box-sizing: border-box; }',
		},

		// WithLayer + preflight definition object
		{
			layer: 'base',
			preflight: {
				':root': {
					fontSize: '16px',
					lineHeight: '1.5',
				},
			},
		},

		// WithLayer + dynamic function
		{
			layer: 'base',
			preflight: (engine) => {
				const prefix = engine.config.prefix
				return `/* Engine prefix: ${prefix} */`
			},
		},
	],
})

Type helpers

PikaCSS exports identity helpers that improve autocomplete and document intent.

  • defineEngineConfig()
  • defineStyleDefinition()
  • defineSelector()
  • defineShortcut()
  • defineKeyframes()
  • defineVariables()
  • defineEnginePlugin()
ts
import { defineStyleDefinition } from '@pikacss/core'

// defineStyleDefinition() is a type-safe identity helper for style definition objects.
// Use it when you want to define a reusable style object outside of a pika() call,
// with full TypeScript autocomplete and type checking.
const buttonBase = defineStyleDefinition({
	padding: '0.5rem 1rem',
	borderRadius: '0.25rem',
	cursor: 'pointer',
	border: 'none',
	fontSize: '1rem',
})

// Pass the typed definition directly to pika()
const cls = pika(buttonBase)

What most teams should standardize

  • shared selectors
  • token variables
  • shortcut naming
  • plugin usage
  • layer strategy
  • ESLint enforcement for static inputs

Next