# @capsizecss/metrics
Font metrics library for system and Google fonts.
```bash
npm install @capsizecss/metrics
```
## Usage
Import the metrics for your chosen font to pass them directly into [capsize](../core/README.md#createstyleobject).
```ts
import { createStyleObject } from '@capsizecss/core';
import arialMetrics from '@capsizecss/metrics/arial';
const capsizeStyles = createStyleObject({
fontSize: 16,
leading: 24,
fontMetrics: arialMetrics,
});
```
In addition to common system fonts, Google fonts are also supported.
```ts
import { createStyleObject } from '@capsizecss/core';
import lobsterMetrics from '@capsizecss/metrics/lobster';
const capsizeStyles = createStyleObject({
fontSize: 16,
leading: 24,
fontMetrics: lobsterMetrics,
});
```
## Variants
Metrics for the available variants of a font can be imported by weight and font style.
```ts
import metrics from '@capsizecss/metrics/ {font-family} / {weight}{style}';
```
The format follows the convention used by Google Fonts for variant names: either a standalone weight or style (e.g. `regular`, `italic`), a specific weight (e.g. numeric `100` to `900`), or a combination of both (e.g. `100italic`-`900italic`).
> [!NOTE]
> Each font only includes the variants that are available for that specific font.
```ts
import arialRegular from '@capsizecss/metrics/arial/regular';
import arialItalic from '@capsizecss/metrics/arial/italic';
import arialBold from '@capsizecss/metrics/arial/700';
import arialBoldItalic from '@capsizecss/metrics/arial/700italic';
```
The top-most import path for a font family (e.g. without a variant: `@capsizecss/metrics/arial`) will return the `regular` variant.
In the case of a Google Font that has no `regular` variant, the first variant in the variants array is returned.
## Font metrics
The font metrics object returned contains the following properties if available:
| Property | Type | Description |
| -------------- | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| familyName | string | The font’s family name as authored by font creator |
| fullName | string | The font’s full name as authored by font creator |
| postscriptName | string | The font’s unique PostScript name as authored by font creator |
| category | string | The style of the font: serif, sans-serif, monospace, display, or handwriting. |
| capHeight | number | The height of capital letters above the baseline |
| ascent | number | The height of the ascenders above baseline |
| descent | number | The descent of the descenders below baseline |
| lineGap | number | The amount of space included between lines |
| unitsPerEm | number | The size of the font’s internal coordinate grid |
| xHeight | number | The height of the main body of lower case letters above baseline |
| xWidthAvg | number | The average width of character glyphs in the font for the selected unicode subset. Calculated based on character frequencies in written text ([see below]), falling back to the built in [xAvgCharWidth] from the OS/2 table. |
| subsets | {
[subset]: { xWidthAvg: number }
} | A lookup of the `xWidthAvg` metric by subset (see [supported subsets below]) |
[supported subsets below]: #subsets
#### How `xWidthAvg` is calculated
The `xWidthAvg` metric is derived from character frequencies in written language.
The value takes a weighted average of character glyph widths in the font, falling back to the built in [xAvgCharWidth] from the OS/2 table if the glyph width is not available.
The purpose of this metric is to support generating CSS metric overrides (e.g. [`ascent-override`], [`size-adjust`], etc) for fallback fonts, enabling inference of average line lengths so that a fallback font can be scaled to better align with a web font. This can be done either manually or using [`createFontStack`].
For this technique to be effective, the metric factors in a character frequency weightings as observed in written language, using “abstracts” from [Wikinews] articles as a data source.
Below is the source analysed for each supported subset:
| Subset | Language |
| ------- | -------------------------------------------- |
| `latin` | English ([source](https://en.wikinews.org/)) |
| `thai` | Thai ([source](https://th.wikinews.org/)) |
> [!TIP]
> Need support for a different unicode subset?
> Either create an issue or follow the steps outlined in the [`generate-weightings` script] in the `unpack` package and open a PR.
For more information on how to access the metrics for different subsets, see the [subsets](#subsets) section below.
[`generate-weightings` script]: ../unpack/scripts/generate-weightings.ts
[see below]: #how-xwidthavg-is-calculated
[xavgcharwidth]: https://learn.microsoft.com/en-us/typography/opentype/spec/os2#xavgcharwidth
[`ascent-override`]: https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/ascent-override
[`size-adjust`]: https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/size-adjust
[`createfontstack`]: ../core/README.md#createfontstack
[wikinews]: https://www.wikinews.org/
## Subsets
The top level `xWidthAvg` metric represents the average character width for the `latin` subset. However, the `xWidthAvg` for each supported subset is available explicitly within the `subsets` field.
For example:
```ts
import arial from '@capsizecss/metrics/arial';
const xWidthAvgDefault = arial.xWidthAvg;
const xWidthAvgLatin = arial.subsets.latin.xWidthAvg; // Same as above
const xWidthAvgThai = arial.subsets.thai.xWidthAvg;
```
## Supporting APIs
### `fontFamilyToCamelCase`
A helper function to support tooling that needs to convert the font family name to the correct casing for the relevant metrics import.
```ts
import { fontFamilyToCamelCase } from '@capsizecss/metrics';
const familyName = fontFamilyToCamelCase('--apple-system'); // => `appleSystem`
const metrics = await import(`@capsizecss/metrics/${familyName}`);
```
### `entireMetricsCollection`
Provides the entire metrics collection as a JSON object, keyed by font family name.
---
**⚠️ CAUTION: Importing this will result in a _large JSON structure_ being pulled into your project!**
**It is not recommended to use this client side.**
---
```ts
import { entireMetricsCollection } from '@capsizecss/metrics/entireMetricsCollection';
const metrics = entireMetricsCollection['arial'];
```
or for a specific variant:
```ts
import { entireMetricsCollection } from '@capsizecss/metrics/entireMetricsCollection';
const arialBoldItalic = entireMetricsCollection['arial'].variants['700italic'];
```
## Thanks
- [SEEK](https://www.seek.com.au) for giving us the space to do interesting work.
## License
MIT.