# Typography.js: generating CSS from a JavaScript typography config

> Typography.js turns a JavaScript object of font, size and rhythm settings into a full stylesheet for block and inline elements. It suits developers who want to tune type scales in code and ship the result as CSS, not a hand-written stylesheet.

**KyleAMathews/typography.js** — A powerful toolkit for building websites with beautiful design

- Repository: https://github.com/KyleAMathews/typography.js
- Website: http://kyleamathews.github.io/typography.js/
- Stars: 3,854 · Forks: 180
- Language: JavaScript
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/kyleamathews-typography-js

## What problem Typography.js solves and who it is for

Hand-written CSS typography is a graph of dependent values. Change the base font size and the line heights, heading margins and vertical rhythm all drift out of alignment. The README frames this plainly: typography is a system of interrelated styles, and "100s of style declarations on dozens of elements must be in harmonious order." Typography.js replaces that manual recalculation with a configuration object plus an engine that emits the CSS. You state intent (base size, line height, font families, scale) and the engine derives the rest. The audience is JavaScript developers building sites where styles already live in the build, most visibly Gatsby sites, since the README lists the Gatsby Blog Starter and several personal sites among its users. It is a poor fit for anyone who wants to edit CSS directly, because the output is generated rather than authored.

## How the Typography engine turns options into CSS

The core is a class you instantiate with a plain object. The README's example sets baseFontSize, baseLineHeight, headerFontFamily and bodyFontFamily, and notes that a full option list exists further down the page, which the truncated README does not show. From those inputs the engine produces styles for block and inline elements. Two output paths are documented: typography.toString() returns the CSS as a string, and typography.injectStyles() inserts it directly into the document head, which the README says "works well for client-only JS web apps." The package also exposes a rhythm function. In the override example it appears as rhythm(1/2) and rhythm(2) for marginBottom and marginTop, so spacing is expressed as multiples of a vertical unit rather than fixed pixel values. Themes are plain JavaScript objects and plugins are functions that extend or modify the engine, for example to change how headers are styled or to add styles for code and tables. The repository is a Lerna monorepo: packages/ holds the theme packages, src/ holds the engine, and the root package.json is marked private with scripts that delegate through lerna run build and lerna publish.

## Installing typography and rendering your first stylesheet

The README gives a single install command for the core package. Run it in your project root:

```bash
npm install typography
```

Then instantiate the class with your own values and print the CSS. The README's JavaScript usage example is the shape to copy:

```javascript
import Typography from 'typography'

const typography = new Typography({
  baseFontSize: '18px',
  baseLineHeight: 1.45,
  headerFontFamily: ['Avenir Next', 'Helvetica Neue', 'Segoe UI', 'Helvetica', 'Arial', 'sans-serif'],
  bodyFontFamily: ['Georgia', 'serif'],
})

typography.toString()
```

Calling toString() returns the generated CSS, so log it or write it to a file and inspect which selectors the engine produced before wiring it into a build. If you would rather skip configuration, install a theme package and pass it straight in. The README uses Funston as the example:

```javascript
import Typography from 'typography'
import funstonTheme from 'typography-theme-funston'

const typography = new Typography(funstonTheme)
```

The theme is a JavaScript object, so you can mutate it before construction (the README sets funstonTheme.baseFontSize = '22px') or attach an overrideThemeStyles function that receives rhythm and options and returns a style object. The README does not document a CLI, so all generation happens through this API at build time or in the browser.

## The constraint that matters most: no single stylesheet to ship

Typography.js is a generator, not a stylesheet. Every consumer needs the typography package installed and the config executed, whether at build time or in the browser. The README's own framing of injectStyles() as suited to "client-only JS web apps" makes the trade-off explicit: that path puts generated CSS into the head at runtime. If your pages are server-rendered or statically generated, you have to capture toString() output and route it into the build yourself, and the README does not describe that pipeline. A second limitation is the theme ecosystem. Themes are separate npm packages, so a project carries the core package plus whichever theme it picked, and each one is a dependency you have to keep resolvable. Third, the README's install example uses an ES module import, and the repository's build tooling is Babel-based (babel-cli, babel-preset-es2015, babel-preset-stage-0), so the package expects a bundler or transpile step rather than a plain script tag. If you just need a fixed set of type rules you will edit twice a year, a hand-written stylesheet is less machinery for the same result.

## How the theme packages differ from a CSS framework

Bootstrap is the obvious comparison, and the difference is not cosmetic. Bootstrap ships a stylesheet you include and override with your own rules; the cascade decides what wins, and the typography values live inside the framework's source. Typography.js inverts that. The values live in your project as a JavaScript object, and the CSS is an artifact of running the engine. The README makes this concrete by publishing typography-theme-bootstrap alongside the other themes, so you can take Bootstrap's typographic proportions as a starting object and change baseFontSize or override styles without touching a framework file. The cost is that you now own a generation step. With Bootstrap, upgrading means swapping a file. With a Typography.js theme, upgrading means a new npm version of that theme package and a rebuild, and any overrideThemeStyles function you attached has to keep working against whatever the new theme object looks like. Pick the framework when you want a finished stylesheet; pick Typography.js when the type scale is something your team edits and reviews like code.

## Maintenance status, licence and upgrade cost

The repository is not archived, and its last push was on 2026-03-04, which is roughly six months before the date of this article. That is recent enough that the project has not been abandoned, but the published release history tells a different story: the most recent release listed is v0.15.0 from 2016-11-02, followed by v0.14.0 and v0.13.0 in the same year. Anyone adopting this should treat the core API as stable by age rather than by active release cadence, and should check the current npm version of the core package and of the theme package they intend to use rather than assuming the changelog reflects what is on the registry. The licence is MIT, which permits commercial and private use and modification, and the repository ships a LICENSE file at the root. That is a permissive arrangement, but it is not legal advice, and if you vendor or fork a theme you should read the LICENSE yourself. The monorepo layout matters for upgrades: because themes are published independently through the Lerna setup, a theme can move without the engine moving, so pin both.

## What to check before you commit to Typography.js

Start from the playground the README links at kyleamathews.github.io/typography.js, which is where the theme catalogue is meant to be explored. Once you have a candidate theme, install it, construct the Typography object, and read the output of toString() on your own content before it reaches a build. The two things worth verifying are the generated selector list (does it cover the elements your pages actually use, including code and tables, or do you need a plugin?) and the behaviour of any overrideThemeStyles function you add, since it receives rhythm and options and returns a style object whose keys are selectors. If your site is client-only, injectStyles() removes the need for a build step; if it is not, plan the toString() capture into your build pipeline, because the README does not describe one.

## Conclusion

Adopt Typography.js if your site is built in JavaScript and you want the type scale expressed as data you can version, review and override per project, with a theme package as the starting point. Do not adopt it if you need a maintained stylesheet you can hand to a designer, or if you cannot tolerate the theme packages being separate npm dependencies. Before committing, run typography.toString() on your real config and read the generated CSS, then check whether the theme package you picked still installs cleanly against your bundler and Node version.

## FAQ

### What is Typography.js used for?

It generates CSS for block and inline elements from a JavaScript configuration object, so a site's type scale is defined in code rather than written by hand. The README describes it as a toolkit for expressing typographic design intent through a high-level API.

### How do I install Typography.js?

The README gives npm install typography for the core package. Themes are separate packages, so a themed setup also needs something like npm install --save typography-theme-funston.

### How do I get the CSS out of Typography.js?

Two paths are documented: typography.toString() returns the generated CSS as a string, and typography.injectStyles() inserts the styles directly into the document head, which the README says works well for client-only JS web apps.

### Can I customize a Typography.js theme?

Yes. Themes are plain JavaScript objects, so you can change a value directly, as the README does with funstonTheme.baseFontSize = '22px', or attach an overrideThemeStyles function that receives rhythm and options and returns a style object.

### What is the rhythm function in Typography.js?

It expresses spacing as multiples of the vertical rhythm unit instead of fixed values. The README's override example uses rhythm(1/2) for marginBottom and rhythm(2) for marginTop on h2 and h3.

## Sources

- [KyleAMathews/typography.js on GitHub](https://github.com/KyleAMathews/typography.js)
- [License: MIT](https://github.com/KyleAMathews/typography.js/blob/master/LICENSE)
- [Project website](http://kyleamathews.github.io/typography.js/)
- [README](https://github.com/KyleAMathews/typography.js/blob/master/README.md)
- [Releases](https://github.com/KyleAMathews/typography.js/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/kyleamathews-typography-js
