Skip to content

First Pika

After installing the build plugin and importing pika.css, you can start writing styles with pika(...).

Prerequisites

Make sure you have already:

  1. Installed @pikacss/unplugin-pikacss and registered the plugin in your bundler config.
  2. Imported pika.css in your application entry point.
ts
import { createApp } from 'vue'

import App from './App.vue'
// src/main.ts
import 'pika.css' // Import the generated CSS

createApp(App)
	.mount('#app')

A minimal first example

pika() is a global function that accepts style objects with camelCase CSS properties. It returns class name(s) that you can bind to elements.

Global Function — No Import Needed

pika() is registered as a global function by the build plugin. You do not need to import it — just use it directly in any source file. The build plugin finds all pika() calls via static analysis and replaces them with generated class names at build time. The pika.gen.ts file provides TypeScript type declarations (via declare global) for editor autocomplete, but it is not a module you import from.

vue
<template>
	<button
		:class="pika({
			padding: '0.5rem 1rem',
			borderRadius: '0.5rem',
			backgroundColor: '#0ea5e9',
			color: 'white',
			border: 'none',
			cursor: 'pointer',
			fontSize: '1rem',
		})"
	>
		Hello PikaCSS
	</button>
</template>
ts
// In vanilla JS/TS, pika() is a global function
// available after setting up the build plugin.

const className = pika({
	padding: '0.5rem 1rem',
	borderRadius: '0.5rem',
	backgroundColor: '#0ea5e9',
	color: 'white',
	border: 'none',
	cursor: 'pointer',
	fontSize: '1rem',
})

// Use the returned class name(s) on any DOM element
document.querySelector('#my-button')!.className = className

What happens at build time

PikaCSS works entirely at build time — there is zero runtime overhead. When you run your build, PikaCSS:

  1. Scans your source files for pika(...) calls.
  2. Analyzes the style objects statically (arguments must be analyzable at build time).
  3. Generates atomic CSS classes — each CSS property-value pair becomes its own class.
  4. Replaces every pika(...) call with the resulting class name string(s).
  5. Writes the atomic CSS rules into the generated stylesheet (pika.gen.css).

Source vs. compiled output

Your pika() call in source code:

vue
<template>
	<button
		:class="pika({
			padding: '0.5rem 1rem',
			borderRadius: '0.5rem',
			backgroundColor: '#0ea5e9',
			color: 'white',
			border: 'none',
			cursor: 'pointer',
			fontSize: '1rem',
		})"
	>
		Hello PikaCSS
	</button>
</template>

Gets compiled to static class names in the output:

html
<!-- After build, pika() calls are replaced with class name strings -->
<button class="a b c d e f g">
  Hello PikaCSS
</button>

And the generated pika.gen.css contains one atomic rule per property:

css
/* Each CSS property becomes its own atomic class */
.a {
  padding: 0.5rem 1rem;
}
.b {
  border-radius: 0.5rem;
}
.c {
  background-color: #0ea5e9;
}
.d {
  color: white;
}
.e {
  border: none;
}
.f {
  cursor: pointer;
}
.g {
  font-size: 1rem;
}

Why atomic CSS?

Each CSS property-value pair is extracted to a single, reusable class. If another element uses color: 'white', it will share the same .d class. This deduplication keeps the stylesheet small as your app grows.

Nested selectors

Style objects support nested selectors for pseudo-classes, media queries, and custom selectors. Nest them as keys in the style object — PikaCSS compiles each nested property to its own atomic class.

vue
<template>
	<button
		:class="pika({
			'padding': '0.5em 1em',
			'borderRadius': '0.25em',
			'border': 'none',
			'backgroundColor': '#0ea5e9',
			'color': 'white',
			'cursor': 'pointer',
			'transition': 'transform 0.2s ease',

			':hover': {
				transform: 'scale(1.05)',
			},

			':active': {
				transform: 'scale(0.95)',
			},
		})"
	>
		Hover me
	</button>
</template>

This produces the following atomic CSS:

css
/* Base styles become atomic classes */
.a {
  padding: 0.5em 1em;
}
.b {
  border-radius: 0.25em;
}
.c {
  border: none;
}
.d {
  background-color: #0ea5e9;
}
.e {
  color: white;
}
.f {
  cursor: pointer;
}
.g {
  transition: transform 0.2s ease;
}

/* Pseudo-selectors also become atomic classes */
.h:hover {
  transform: scale(1.05);
}
.i:active {
  transform: scale(0.95);
}

Multiple arguments

pika() accepts multiple arguments (each is a StyleItem). An argument may be a style object or a string (for shortcuts defined in your config). They are merged in order:

vue
<template>
	<!-- pika() accepts multiple arguments (StyleItem[]) -->
	<!-- Each argument can be a string (shortcut) or a style object -->
	<div
		:class="pika(
			'my-shortcut',
			{
				fontSize: '1.5rem',
				color: '#333',
			},
		)"
	>
		Combining shortcuts and inline styles
	</div>
</template>

Output format variants

By default, pika() returns a space-separated string of class names (e.g. "a b c"). It also exposes variants for different output formats:

ts
// pika() - Default output format (configured by integration, usually string)
const classes = pika({ color: 'red', fontSize: '1rem' })
// => "a b" (string of space-separated class names)

// pika.str() - Force string output
const str = pika.str({ color: 'red', fontSize: '1rem' })
// => "a b"

// pika.arr() - Force array output
const arr = pika.arr({ color: 'red', fontSize: '1rem' })
// => ["a", "b"]
VariantReturn typeUse case
pika()ConfiguredDefault (usually string)
pika.str()stringForce space-separated string
pika.arr()string[]Force array of class names

IDE preview with pikap

pikap is a preview variant of pika. It has the same API, but provides CSS preview tooltips directly in your IDE. Use pikap during development to see the generated CSS without running a build.

Configuration (optional)

PikaCSS works with zero configuration, but you can create a pika.config.ts (or .js, .mjs, .mts, .cjs, .cts) to customize behavior. Use the defineEngineConfig() helper for full TypeScript autocomplete:

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

export default defineEngineConfig({
	// Prefix for generated class names (default: '')
	prefix: '',

	// Selector pattern, '%' is replaced with the class ID (default: '.%')
	defaultSelector: '.%',

	// Plugins to extend functionality
	plugins: [],

	// Global CSS injected before atomic styles
	preflights: [],
})

The config file is auto-detected by the plugin. See Configuration for all available options.

Why this matters

You keep a CSS-in-JS authoring experience — standard CSS properties, TypeScript autocomplete, object composition — while shipping static CSS output with no runtime style generation overhead.

Next