Library / SDK
frenic/csstype avatar
frenic/csstype

csstype turns an MDN data dump into strict style typings

Strict TypeScript and Flow types for style based on MDN data

1,816 stars75 forksTypeScriptMIT

At a glance

What is it?
csstype generates TypeScript and Flow definitions for CSS from MDN's browser compatibility data, and splits them along two axes, property category and casing, so you can type only the standard properties you actually use. It ships no runtime code, which is why the package main field is empty and everything lives in the types entry.
Who is it for?
Adopt csstype when your project hand-writes style objects in TypeScript and you want invalid property names and values to fail at compile time. Do not add it to a project that uses a CSS-in-JS library with its own types, since the two will overlap.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Two lines of code that fail to compile

The README leads with the failure case, because that is the whole product. Both of these are type errors:

ts
import type * as CSS from 'csstype';

const style: CSS.Properties = {
  colour: 'white', // Type error on property
  textAlign: 'middle', // Type error on value
};

The first is a misspelling of color, caught because the property name is a literal in a union rather than an index signature. The second is text-align, which accepts left, right, center and justify but not middle, so the value literal is checked against the real set.

That combination is why this package exists. csstype provides type checking for CSS property names and values.

Types only, so main is empty

The manifest makes the shape of the package obvious: main is an empty string and types points at index.d.ts. There is no JavaScript to ship, which is why the README can show a type-only import and nothing else at runtime.

That is a real engineering decision with consequences. A consumer's bundler resolves no module for a type-only import, so adding csstype costs nothing in bundle size. It also means the package cannot be used at runtime to validate a style object, and there is no helper function to coerce a string into a known property.

Flow consumers get the same data through a separate declaration file, index.js.flow, and a .flowconfig at the repository root. The README notes the at-rule types differ between the two languages, appearing in an AtRule namespace in TypeScript and prefixed with AtRule$ in Flow.

The category axis decides how strict you are

Properties are grouped into categories that you choose between rather than one exhaustive list. All includes everything. Standard covers current properties and extends StandardLonghand and StandardShorthand subcategories. Vendor covers prefixed properties with their own longhand and shorthand sets. Obsolete covers removed or deprecated properties, and Svg covers SVG specific ones.

The README's example of the trade-off is blunt: with Properties, misspelling colour is caught. Choose StandardProperties and you also lose the ability to write something your browser will reject anyway, which is the point of typing rather than validating at runtime.

For a design system that has decided vendor prefixes are dead weight, StandardProperties is the type you want. For a codebase still carrying prefixed fallbacks, Properties keeps them legal and you rely on the Fallback variants instead.

Casing and fallbacks are separate switches

The second axis is naming and value shape. Default variants use JavaScript camel case, Hyphen variants use CSS kebab case, and Fallback variants additionally accept an array of values.

Fallback variants accept arrays because CSS-in-JS libraries express fallback values as arrays:

ts
import type * as CSS from 'csstype';

const style: CSS.PropertiesFallback = {
  display: ['-webkit-flex', 'flex'],
  color: 'white',
};

Hyphen casing is not included by default, and the README is careful to say it is not added to Properties. You opt in by extending, which lets a single style object carry both spellings:

ts
interface Style extends CSS.Properties, CSS.PropertiesHyphen {}

const style: Style = {
  'flex-grow': 1,
  'flex-shrink': 0,
  'font-weight': 'normal',
  backgroundColor: 'white',
};

Pseudo selectors get their own literals. SimplePseudos covers plain ones like:hover, while AdvancedPseudos covers function-like ones such as:not, stored as the string excluding the parenthesis, since the argument creates an unbounded number of variations.

Generics for platforms that accept bare numbers

Every interface takes two optional generic parameters, CSS.Properties<TLength = string | 0, TTime = string>. The length default includes 0 because it is the only length where the unit is optional, so margin: 0 is legal and margin: 0px is the general form.

If your rendering target accepts a bare number for any length, widen the first parameter and you get numeric values type checked:

tsx
const style: CSS.Properties<string | number> = {
  width: 100,
};

The second parameter does the same for times, which is what a native runtime usually wants:

tsx
const style: CSS.Properties<string | number, number> = {
  transitionDuration: 1000,
};

This lets projects customize the types for platforms and libraries that accept numeric lengths or times.

The package is generated from mdn-data by scripts

Nothing in index.d.ts is written by hand. The repository root is a generator: build.ts runs the build, update.ts fetches newer data, utils.ts holds helpers, and is-clean.ts appears to verify the working tree after generation. The dependencies explain the pipeline, with mdn-data 2.25.0 and @mdn/browser-compat-data 7.1.21 as sources, css-tree for parsing, chokidar for watching in the watch script, and turndown for converting documentation HTML to Markdown.

TypeScript runs at about 5.9.3 in the toolchain, tests use Jest 30 with jsdom for DOM fixtures, and there is a separate __tests__/ directory with its own install step in prepublish. Formatting goes through Prettier and linting through ESLint 9 with typescript-eslint and eslint-plugin-prettier, and releases are cut with release-it configured in .release-it.json.

There is also a lazy script, tsc followed by the linter, which suggests the project itself does not check cleanly on every commit and defers that to the release step.

Version skew, maintenance and where it stops helping

The maintenance signal here needs care. The GitHub releases listed are v2.4.0 on 2018-04-24, v2.5.0 on 2018-05-09 and v2.6.0 on 2018-12-27, while the manifest version is 3.2.3 and the last push was on 2026-04-10, six months before today. So releases after 2.6.0 were published to npm without GitHub release tags, and a 3.x line exists that the repository tags do not describe.

Practically, pin the npm version you use and read the README section on version 3.0, which the table of contents lists as a separate heading, before migrating from a 2.x install.

The README also has a section on what to do when you get type errors, and it is honest about the cause: CSS custom properties, a specification that changes often, and vendors shipping their own implementations on their own schedules. Errors that are wrong in principle will happen. The suggested path starts by confirming the usage is correct, then leads to custom property handling.

For anything that generates CSS from a design token pipeline, or for a project using a CSS-in-JS library that already ships its own property types, csstype adds a second opinion rather than a fix.

Editorial conclusion

Adopt csstype when your project hand-writes style objects in TypeScript and you want invalid property names and values to fail at compile time. Do not add it to a project that uses a CSS-in-JS library with its own types, since the two will overlap. Verify first which category you want, since the default Properties type includes obsolete and vendor prefixed properties, and pin the version deliberately, because the published GitHub releases stop at 2.6.0 while the manifest is already at 3.2.3.

Frequently asked questions

How do I install csstype?

Run npm install csstype. The package contains no runtime code: main is empty and the entry point is the index.d.ts type definitions, so it costs nothing in bundle size when imported as a type.

Which property categories does csstype provide?

All includes Standard, Vendor, Obsolete and Svg. Standard covers current properties, while Vendor covers vendor-prefixed, Obsolete covers removed or deprecated, and Svg covers SVG-specific properties.

How do I allow CSS fallback values in csstype?

Use a Fallback variant such as CSS.PropertiesFallback, which accepts an array of values for any property. That is how CSS-in-JS libraries express fallbacks, for example display: ['-webkit-flex', 'flex'].

Can csstype type numeric values like React Native styles?

Yes, through its two generic parameters. CSS.Properties<TLength, TTime> defaults to string | 0 and string, and widening the first to string | number allows width: 100, while widening the second allows numeric values such as transitionDuration: 1000.

Official sources

  1. frenic/csstype on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/frenic-csstype.svg)](https://hysenlabs.com/projects/frenic-csstype)

Was this useful?