# @capsizecss/core

> Flipping how we define typography

Latest version **4.1.3** (published 2025-11-12) · MIT license · 0 weekly downloads

## Install

```sh
npm install @capsizecss/core
pnpm add @capsizecss/core
yarn add @capsizecss/core
bun add @capsizecss/core
```

## Health

**Score 65/100 (B)** — status: stable.

Positive: has types; esm support; no vulnerabilities; has provenance; high maintenance score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 4.1.3 |
| Published | 2025-11-12 |
| First published | 2021-08-23 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 1 |
| Unpacked size | 46.8 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 1719 |
| Author | Michael Taranto |
| Maintainers | mjt01, seek-oss-ci |
| Keywords | capsize, leading trim, white space, baseline, basekick, cap height, typography, line gap, leading, fallback font, font metrics, ascent override, descent override, line gap override, size adjust, content layout shift, cls |

## Links

- npm: https://www.npmjs.com/package/@capsizecss/core
- Repository: https://github.com/seek-oss/capsize
- Homepage: https://github.com/seek-oss/capsize#readme
- Issues: https://github.com/seek-oss/capsize/issues
- npm.io page: https://npm.io/package/@capsizecss/core

## Dependencies (1)

- [csstype](https://npm.io/package/csstype.md) ^3.1.1

## Alternatives

- [@sindresorhus/slugify](https://npm.io/package/@sindresorhus/slugify.md) — 3.7M weekly downloads
- [solid-js](https://npm.io/package/solid-js.md) — 2.7M weekly downloads
- [expo-glass-effect](https://npm.io/package/expo-glass-effect.md) — 2.5M weekly downloads
- [nanoassert](https://npm.io/package/nanoassert.md) — 780.8K weekly downloads
- [@ffmpeg/ffmpeg](https://npm.io/package/@ffmpeg/ffmpeg.md) — 529.5K weekly downloads

## Recent versions

- 4.1.3 (latest) — 2025-11-12
- 0.0.0-test-20251006235016 (test) — 2025-10-06
- 0.0.0-add-weight-italic-support-20240507114515 (add-weight-italic-support) — 2024-05-07
- 0.0.0-add-subset-support-20240304225850 (add-subset-support) — 2024-03-04
- 0.0.0-metrics-frequency-data-20240215031405 (metrics-frequency-data) — 2024-02-15
- 0.0.0-master-20240214212615 (master) — 2024-02-14
- 0.0.0-crackle-20240208083429 (crackle) — 2024-02-08
- 0.0.0-add-language-support-v2-20231129052138 (add-language-support-v2) — 2023-11-29
- 0.0.0-add-language-support-20231121023926 (add-language-support) — 2023-11-21
- 0.0.0-create-font-stack-20221130045640 (create-font-stack) — 2022-11-30
- 0.0.0-createfontstack-20221110224822 (createfontstack) — 2022-11-10
- 4.1.2 — 2024-05-08
- 0.0.0-add-weight-italic-support-20240507015549 — 2024-05-07
- 4.1.1 — 2024-05-05
- 4.1.0 — 2024-03-08
- … 10 more at https://npm.io/package/@capsizecss/core/versions

## README

<img src="https://raw.githubusercontent.com/seek-oss/capsize/HEAD/images/capsize-header.png#gh-light-mode-only" alt="Capsize" title="Capsize" width="443px" />
<img src="https://raw.githubusercontent.com/seek-oss/capsize/HEAD/images/capsize-header-inverted.png#gh-dark-mode-only" alt="Capsize" title="Capsize" width="443px" />
<br/>

> Capsize makes the sizing and layout of text as predictable as every other element on the screen.
>
> Using font metadata, text can now be sized according to the height of its capital letters while trimming the space above capital letters and below the baseline.

```bash
npm install @capsizecss/core
```

- [Usage](#usage)
  - [createStyleObject](#createstyleobject)
  - [createStyleString](#createstylestring)
- [Options](#options)
  - [Text size](#text-size)
  - [Line height](#line-height)
  - [Font Metrics](#font-metrics)
- [Core](#core)
  - [createFontStack](#createfontstack)
    - [Usage in CSS stylesheet](#usage-in-css-stylesheet-or-a-style-tag)
    - [Usage with CSS-in-JS frameworks](#usage-with-css-in-js-frameworks)
    - [Additional `font-face` properties](#providing-additional-font-face-properties)
  - [precomputeValues](#precomputevalues)
  - [getCapHeight](#getcapheight)
- [Metrics](#metrics)
- [Unpack](#unpack)
- [Integrations](#integrations)
  - [vanilla-extract](../../packages/vanilla-extract/README.md)

## Usage

### `createStyleObject`

Returns a CSS-in-JS style object.

1. Import `createStyleObject` passing the relevant [options](#options).

```ts
import { createStyleObject } from '@capsizecss/core';

const capsizeStyles = createStyleObject({
  fontSize: 16,
  leading: 24,
  fontMetrics: {
    capHeight: 700,
    ascent: 1058,
    descent: -291,
    lineGap: 0,
    unitsPerEm: 1000,
  },
});
```

Note: It is recommended that you install the [@capsizecss/metrics](../../packages/metrics/README.md) package and import the metrics from there:

```ts
import { createStyleObject } from '@capsizecss/core';
import arialMetrics from '@capsizecss/metrics/arial';

const capsizeStyles = createStyleObject({
  fontSize: 16,
  leading: 24,
  fontMetrics: arialMetrics,
});
```

See the [fontMetrics](#font-metrics) option documented below for more ways to obtain these metrics.

2. Apply styles to the text element, for example via the `css` prop.

```ts
<div
  css={{
    // fontFamily: '...' etc,
    ...capsizeStyles,
  }}
>
  My capsized text 🛶
</div>
```

> ⚠️ Note: It is not recommended to apply further layout-related styles to the same element, as this will risk interfering with the styles used for the trim. Instead consider using a nested element.

### `createStyleString`

Returns a CSS string that can be inserted into a `style` tag or appended to a stylesheet.

1. Import `createStyleString` passing the relevant [options](#options).

```ts
import { createStyleString } from '@capsizecss/core';
import arialMetrics from '@capsizecss/metrics/arial';

const capsizedStyleRule = createStyleString('capsizedText', {
  fontSize: 16,
  leading: 24,
  fontMetrics: arialMetrics,
});
```

2. Add the styles into a stylesheet or `style` element and apply the specified class name.

```ts
document.write(`
  <style type="text/css">
    ${capsizedStyleRule}
  </style>
  <div class="capsizedText">
    My capsized text 🛶
  </div>
`);
```

> ⚠️ Note: It is not recommended to apply further layout-related styles to the same element, as this will risk interfering with the styles used for the trim. Instead consider using a nested element.

## Options

### Text size

Capsize supports two methods of defining the size of text, `capHeight` and `fontSize`.

**NOTE: You should only ever pass one or the other, not both.**

#### `capHeight: <number>`

Sets the height of the capital letters to the defined value. Defining typography in this way makes aligning to a grid or with other elements, e.g. icons, a breeze.

<img src="https://raw.githubusercontent.com/seek-oss/capsize/HEAD/images/capheight.png" alt="Highlighting the cap height" title="Cap Height" width="220px" />

#### `fontSize: <number>`

Setting the font size allows you to get all the benefits of the white space trimming, while still specifying an explicit `font-size` for your text. This can be useful when needed to match a concrete design spec or fitting into an existing product.

<img src="https://raw.githubusercontent.com/seek-oss/capsize/HEAD/images/fontsize.png" alt="Highlighting the font size" title="Font Size" width="220px" />

### Line height

Capsize supports two mental models for specifying line height, `lineGap` and `leading`. If you pass neither the text will follow the default spacing of the specified font, e.g. `line-height: normal`.

**NOTE: You should only ever pass one or the other, not both.**

#### `lineGap: <number>`

Sets the number of pixels between lines, as measured between the baseline and cap height of the next line.

<img src="https://raw.githubusercontent.com/seek-oss/capsize/HEAD/images/linegap.png" alt="Highlighting the line gap" title="Line Gap" width="220px" />

#### `leading: <number>`

Sets the line height to the provided value as measured from the baseline of the text. This aligns the web with how typography is treated in design tools.

<img src="https://raw.githubusercontent.com/seek-oss/capsize/HEAD/images/leading.png" alt="Highlighting the leading" title="Leading" width="220px" />

### Font Metrics

This metadata is extracted from the metrics tables inside the font itself. There are a number of ways to find this information:

- If using a Google Font or system font, install the [@capsizecss/metrics](../../packages/metrics/README.md) package and import the metrics by name. For example:
  ```ts
  import arialMetrics from '@capsizecss/metrics/arial';
  ```
- If using a font from a file, install the [@capsizecss/unpack](../../packages/unpack/README.md) package and extract the metrics from the font file directly. For example:

  ```ts
  import { fromFile } from '@capsizecss/unpack';

  const metrics = await fromFile(filePath);
  ```

- Or, use [the Capsize website](https://seek-oss.github.io/capsize/) to find these by selecting a font and referencing `Metrics` tab in step 3.

## Core

The core package also provides a few other metrics-based features for improving typography on the web:

### createFontStack

Creates metrics-based `@font-face` declarations to improve the alignment of font family fallbacks, which can dramatically improve the [Cumulative Layout Shift](https://web.dev/cls/) metric for sites that depend on a web font.

#### Usage

Consider the following example, where the desired web font is [Lobster](https://fonts.google.com/specimen/Lobster), falling back to `Helvetica Neue` and then `Arial`, e.g. `font-family: Lobster, 'Helvetica Neue', Arial`.

1. Import `createFontStack` from the core package:

```ts
import { createFontStack } from '@capsizecss/core';
```

2. Import the font metrics for each of the desired fonts (see [Font Metrics](#font-metrics) above):

```ts
import lobster from '@capsizecss/metrics/lobster';
import helveticaNeue from '@capsizecss/metrics/helveticaNeue';
import arial from '@capsizecss/metrics/arial';
```

3. Create your font stack passing the metrics as an array, using the same order as you would via the `font-family` CSS property.

```ts
const { fontFamily, fontFaces } = createFontStack([
  lobster,
  helveticaNeue,
  arial,
]);
```

The returned value contains the generated font face declarations as well as the computed `fontFamily` with the appropriately ordered font aliases.

#### Usage in CSS stylesheet or a style tag

The returned values can be templated into a stylesheet or a `style` block. Here is an example [handlebars](https://handlebarsjs.com/) template:

```html
<style type="text/css">
  .heading {
    font-family: {{ fontFamily }}
  }

  {{ fontFaces }}
</style>
```

This will produce the following CSS:

```css
.heading {
  font-family:
    Lobster, 'Lobster Fallback: Helvetica Neue', 'Lobster Fallback: Arial',
    'Helvetica Neue', Arial;
}

@font-face {
  font-family: 'Lobster Fallback: Helvetica Neue';
  src: local('Helvetica Neue');
  ascent-override: 115.1741%;
  descent-override: 28.7935%;
  size-adjust: 86.8251%;
}
@font-face {
  font-family: 'Lobster Fallback: Arial';
  src: local('Arial');
  ascent-override: 113.5679%;
  descent-override: 28.392%;
  size-adjust: 88.053%;
}
```

#### Usage with CSS-in-JS frameworks

If working with a CSS-in-JS library, the returned `fontFaces` can be provided as a JavaScript style object by providing `styleObject` as a `fontFaceFormat` option.

Here is an example using [Emotion](https://emotion.sh/):

```tsx
import { Global } from '@emotion/core';

const { fontFaces, fontFamily } = createFontStack(
  [lobster, helveticaNeue, arial],
  {
    fontFaceFormat: 'styleObject',
  },
);

export const App = () => (
  <>
    <Global styles={fontFaces} />
    <p css={{ fontFamily }}>...</p>
  </>
);
```

> Also useful as a source for further manipulation given it is a data structure that can be iterated over or extended.

#### Providing additional `font-face` properties

Additional properties can be added to the generated `@font-face` declarations via the `fontFaceProperties` option:

```ts
const { fontFamily, fontFaces } = createFontStack(
  [lobster, helveticaNeue, arial],
  {
    fontFaceProperties: {
      fontDisplay: 'swap',
    },
  },
);
```

This will result in the following additions to the declarations:

```diff
 @font-face {
   font-family: 'Lobster Fallback: Helvetica Neue';
   src: local('Helvetica Neue');
   ascent-override: 115.1741%;
   descent-override: 28.7935%;
   size-adjust: 86.8251%;
+  font-display: swap;
 }
 @font-face {
   font-family: 'Lobster Fallback: Arial';
   src: local('Arial');
   ascent-override: 113.5679%;
   descent-override: 28.392%;
   size-adjust: 88.053%;
+  font-display: swap;
 }
```

> [!NOTE]
> Passing any of the metric override CSS properties will be ignored as they are calculated by Capsize.
> However, the `size-adjust` property is accepted to support fine-tuning the override for particular use cases.
> This can be used to finesse the adjustment for specific text, or to disable the adjustment by setting it to `100%`.

#### Scaling for different character subsets

For languages that use different unicode subsets, e.g. Thai, the fallbacks need to be scaled accordingly, as the scaling is [based on character frequency in written language].

A fallback font stack can be generated for a supported subset by specifying `subset` as an option:

```ts
const { fontFamily, fontFaces } = createFontStack([lobster, arial], {
  subset: 'thai',
});
```

> [!TIP]
> Need support for a different unicode subset?
> Either create an issue or follow the steps outlined in the [`generate-weightings` script] and open a PR.

[based on character frequency in written language]: ../../packages/metrics/README.md#how-xwidthavg-is-calculated
[`generate-weightings` script]: ../../packages/unpack/scripts/generate-weightings.ts

### precomputeValues

Returns all the information required to create leading trim styles for a specific font size given the provided font metrics. This is useful for integrations with different styling solutions.

Accepts the same [options](#options) as [createStyleObject](#createstyleobject) and [createStyleString](#createstylestring).

```ts
import { precomputeValues } from '@capsizecss/core';
import arialMetrics from '@capsizecss/metrics/arial';

const capsizeValues = precomputeValues({
  fontSize: 16,
  leading: 24,
  fontMetrics: arialMetrics,
});

// => {
//  fontSize: string,
//  lineHeight: string,
//  capHeightTrim: string,
//  baselineTrim: string,
//}
```

### getCapHeight

Return the rendered cap height for a specific font size given the provided font metrics.

```ts
import { getCapHeight } from '@capsizecss/core';
import arialMetrics from '@capsizecss/metrics/arial';

const actualCapHeight = getCapHeight({
  fontSize: 24,
  fontMetrics: arialMetrics,
});

// => number
```

## Metrics

To make the retrieval of font metrics easy, Capsize provides the `@capsizecss/metrics` package containing all the required data for both system and Google fonts.

```bash
npm install @capsizecss/metrics
```

See the [package](../../packages/metrics/README.md) for documentation.

## Unpack

If you are using a custom font or one not included in the `@capsizecss/metrics` package, Capsize provides the `@capsizecss/unpack` package to extract the required data either via a URL or from a local file.

```bash
npm install @capsizecss/unpack
```

See the [package](../../packages/unpack/README.md) for documentation.

## Integrations

- [vanilla-extract](https://vanilla-extract.style) integration via [@capsizecss/vanilla-extract](../../packages/vanilla-extract/README.md)

## Thanks

- [Vincent De Oliveira](https://twitter.com/iamvdo) for writing [Deep dive CSS: font metrics, line-height and vertical-align](https://iamvdo.me/en/blog/css-font-metrics-line-height-and-vertical-align), which provided the research needed to build all this.
- [Devon Govett](https://github.com/devongovett) for creating [Fontkit](https://github.com/foliojs/fontkit), which does all the heavy lifting of extracting the font metrics under the covers.
- [SEEK](https://www.seek.com.au) for giving us the space to do interesting work.

## License

MIT.

---
_Source: https://npm.io/package/@capsizecss/core · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
