Getting Started
Install TypeStyles and ship your first typed component styles in a few minutes
TypeStyles is CSS in TypeScript: style objects (selectors, media queries, pseudos), typed variants, tokens as CSS variables, and ordinary className strings in React, Vue, Svelte, or HTML. No compiler is required for the default runtime path.
You need TypeScript and a bundler or runtime that resolves node_modules (Vite, webpack, Next.js, and others work; no TypeStyles-specific loader for the default path).
Installation
pnpm add typestyles
npm install typestyles
yarn add typestyles
Optional — Vite: for dev HMR and build-time CSS extraction, add @typestyles/vite. Other bundlers: Zero-runtime extraction.
Your first styles
Use createTypeStyles once so styles and tokens share one scopeId (namespaced CSS variables and predictable class names). Put the module in a file you import from your UI — the live example below includes the full source and a className usage snippet.
Scoped button + tokens
Read-only live output. Toggle variants to see the preview, DOM classes, and emitted CSS update together.
Source · app/typestyles.ts
import { createTypeStyles } from 'typestyles';
export const { styles, tokens } = createTypeStyles({ scopeId: 'app' });
export const color = tokens.create('color', {
primary: '#0066ff',
surface: '#ffffff',
});
export const button = styles.component('button', {
base: {
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
padding: '8px 16px',
borderRadius: '6px',
fontWeight: 500,
border: 'none',
cursor: 'pointer',
color: color.surface,
backgroundColor: color.primary,
},
variants: {
intent: {
primary: { backgroundColor: color.primary, color: color.surface },
ghost: {
backgroundColor: 'transparent',
color: color.primary,
border: `1px solid ${color.primary}`,
},
},
},
defaultVariants: { intent: 'primary' },
});
Usage · Button.tsx
<button type="button" className={button({ intent: 'primary' })}>
Example button
</button>
DOM
class="app-button-base app-button-intent-primary"
Emitted CSS
:root {
--app-color-primary: #0066ff;
--app-color-surface: #ffffff;
}
.app-button-base {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 8px 16px;
border-radius: 6px;
font-weight: 500;
border: none;
cursor: pointer;
color: var(--app-color-surface);
background-color: var(--app-color-primary);
}
.app-button-intent-primary {
background-color: var(--app-color-primary);
color: var(--app-color-surface);
}
Toggle Ghost in the demo and check the DOM and Emitted CSS panels (or DevTools on the preview button). Scoped class names are prefixed with your scopeId, and token-backed values resolve to custom properties such as --app-color-primary.
What just happened: definitions register when the module loads; the first time a class is used, TypeStyles injects rules into a managed <style> tag. For SSR, streaming, or static CSS in production, see SSR and Zero-runtime extraction.
For React-specific patterns (refs, merging className, server components), see React integration. Vue and Svelte work the same way — see the runnable examples below.
Runnable examples
Clone the typestyles monorepo and run from the repo root (pnpm install once):
| Example | Command | README |
|---|---|---|
| Vite + React (recommended starting point) | pnpm vite-app dev |
examples/vite-app |
| Next.js App Router + extraction verify | pnpm next-app dev |
examples/next-app |
| Vue 3 | pnpm vue-app dev |
examples/vue-app |
| Svelte 5 | pnpm svelte-app dev |
examples/svelte-app |
| Runtime only (no bundler plugin) | pnpm parcel-app dev |
examples/parcel-app |
Full index: examples/README.md · maintainer map: docs/README.md
Next steps
| Topic | What you will learn |
|---|---|
| Styles | Flat vs dimensioned styles.component, styles.class, composition, mental model |
| Components | Variants, compounds, multipart slots |
| Tokens | Namespaces, themes, tokens.use |
| Framework comparison | How TypeStyles compares to other tools |
| Migration | Mapping from Panda, CVA, StyleX, Emotion |
| Design system with tokens | Primitives → semantics → components |
| Class naming | Semantic vs hashed output |