css-typed-vars
v0.4.2
Published
Generate TypeScript typed constants from CSS custom properties
Maintainers
Readme
var(--color-primary) is just a string. Rename the variable — the error shows up only in the browser.
css-typed-vars scans your CSS files and gives you typed constants. Use cssVars.colorPrimary instead — TypeScript catches missing variables at compile time.
Installation
npm install -D css-typed-varsTwo approaches
| | CLI | Plugin |
|---|---|---|
| How it works | Generates cssVars.ts in your project | Virtual module, no file generated |
| Import | import { cssVars } from './cssVars' | import { cssVars } from 'css-typed-vars/vars' |
| Watch | --watch flag | vite dev, browser reloads automatically |
| Works with | Everything | Vite, webpack, Rollup, esbuild (not Turbopack) |
CLI
Create a config file in your project root:
// css-typed-vars.config.js
export default {
input: 'src/styles/**/*.{css,scss}',
output: 'src/cssVars.ts',
};Then run:
npx css-typed-vars # generate once
npx css-typed-vars --watch # watch for changesAdd to your package.json scripts:
{
"scripts": {
"generate:vars": "css-typed-vars",
"generate:vars:watch": "css-typed-vars --watch"
}
}Given this CSS:
:root {
--color-primary: #3b82f6;
--spacing-md: 8px;
}Generates src/cssVars.ts:
// generated — do not edit
export const cssVars = {
colorPrimary: 'var(--color-primary)',
spacingMd: 'var(--spacing-md)',
} as const;
export type CssVarName = keyof typeof cssVars;CLI flags
npx css-typed-vars --input "src/styles/**/*.css" --output src/cssVars.ts
npx css-typed-vars --input "src/styles/**/*.{css,scss}" --output src/cssVars.ts --watchnpx css-typed-vars --input "src/**/*.css" --output src/cssVars.ts --exclude "**/vendor/**"
npx css-typed-vars --input "src/**/*.css" --output src/cssVars.ts --prefix theme --naming snake
npx css-typed-vars --input "src/**/*.css" --output src/cssVars.js # generates .js + .d.ts
npx css-typed-vars --input "src/**/*.css" --output src/cssVars.ts --selector ".dark"| Flag | Description |
|------|-------------|
| --input | Glob pattern for CSS/SCSS/Less files |
| --output | Output file. .ts → TypeScript, .js → JavaScript + .d.ts alongside |
| --exclude | Glob pattern for files to exclude (single value; use config file for multiple) |
| --prefix | Prefix for generated keys: --prefix theme → themeColorPrimary |
| --naming | Key naming: camelCase (default), snake, kebab |
| --selector | Extra CSS selector to scan for variables (single value; use config file for multiple) |
| --watch | Watch for file changes and regenerate |
| --version, -v | Print the version number and exit |
CLI flags override values from the config file.
Config file
The CLI looks for a config file in the current working directory (in order):
css-typed-vars.config.jscss-typed-vars.config.mjscss-typed-vars.config.json
All options are supported in the config file:
// css-typed-vars.config.js
export default {
input: 'src/styles/**/*.{css,scss}',
output: 'src/cssVars.ts',
exclude: ['**/vendor/**', '**/node_modules/**'],
prefix: 'theme',
naming: 'snake', // 'camelCase' | 'snake' | 'kebab'
selectors: ['.dark', '[data-theme="dark"]'],
};Plugin
No file is generated — CSS variables are served as a virtual module directly by your bundler. Import from css-typed-vars/vars in your source code.
TypeScript types are written to node_modules/css-typed-vars/dist/generated.d.ts automatically on each build or dev server start.
Vite
// vite.config.ts
import { defineConfig } from 'vite';
import cssTypedVars from 'css-typed-vars/vite';
export default defineConfig({
plugins: [
cssTypedVars({ input: 'src/styles/**/*.{css,scss}' }),
],
});// src/index.ts
import { cssVars } from 'css-typed-vars/vars';webpack
// webpack.config.js
import cssTypedVars from 'css-typed-vars/webpack';
export default {
plugins: [cssTypedVars({ input: 'src/styles/**/*.{css,scss}' })],
};Rollup
// rollup.config.js
import cssTypedVars from 'css-typed-vars/rollup';
export default {
plugins: [cssTypedVars({ input: 'src/styles/**/*.{css,scss}' })],
};esbuild
import cssTypedVars from 'css-typed-vars/esbuild';
await esbuild.build({
plugins: [cssTypedVars({ input: 'src/styles/**/*.{css,scss}' })],
});Next.js (webpack)
// next.config.js
const cssTypedVars = require('css-typed-vars/webpack');
module.exports = {
webpack(config) {
config.plugins.push(cssTypedVars({ input: 'styles/**/*.{css,scss}' }));
return config;
},
};Turbopack
Turbopack does not yet have a public plugin API for virtual modules. Use the CLI instead:
{
"scripts": {
"dev": "css-typed-vars && next dev --turbo",
"build": "css-typed-vars && next build"
}
}Plugin options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| input | string \| string[] | — | Glob pattern for CSS/SCSS/Less files |
| exclude | string \| string[] | — | Glob pattern(s) for files to exclude |
| prefix | string | — | Prefix for generated keys: 'theme' → themeColorPrimary |
| naming | 'camelCase' \| 'snake' \| 'kebab' | 'camelCase' | Key naming convention |
| selectors | string[] | — | Extra CSS selectors to scan, e.g. ['.dark', '[data-theme="dark"]'] |
| dts | string \| false | inside node_modules | Path to write type declarations. false to skip |
Usage
React:
import { cssVars } from './cssVars'; // CLI
// or
import { cssVars } from 'css-typed-vars/vars'; // plugin
<div style={{ color: cssVars.colorPrimary, padding: cssVars.spacingMd }} />styled-components / emotion:
const Button = styled.button`
color: ${cssVars.colorPrimary};
padding: ${cssVars.spacingMd};
`;Vue:
<div :style="{ color: cssVars.colorPrimary }" />Svelte:
<div style:color={cssVars.colorPrimary} />Tailwind arbitrary values:
<div className={`text-[${cssVars.colorPrimary}]`} />Programmatic API
import { generate } from 'css-typed-vars';
await generate({
input: 'src/styles/**/*.{css,scss}',
output: 'src/cssVars.ts', // or 'src/cssVars.js' → generates .js + .d.ts
exclude: ['**/vendor/**'],
prefix: 'theme',
naming: 'snake', // 'camelCase' | 'snake' | 'kebab'
selectors: ['.dark', '[data-theme="dark"]'],
});Lower-level exports:
import { parseVarNames, generateCode, scanVarNames } from 'css-typed-vars';Supported formats
| Format | Extension |
|--------|-----------|
| CSS | .css |
| SCSS | .scss |
| Less | .less |
By default, variables are scanned from :root {} blocks (including attribute selectors like :root[data-theme="dark"]). Use the selectors option to also pick up variables from other selectors such as .dark or [data-theme="dark"].
Contributing
Contributions are welcome. Please open an issue before submitting a pull request.
git clone https://github.com/StanislavKozachenko/css-typed-vars.git
cd css-typed-vars
npm install
npm testLicense
MIT
