# Typography

Each type-* class sets the whole type stack at once. Read this for the roles, the sizes and the modifiers you chain onto them.

Typography ships as `type-*` classes, one per role and size. Each class sets
`font-family`, `font-weight`, `font-size`, `line-height` and `text-transform`
in one declaration, and the `type-surface-*` roles set `letter-spacing` as
well, so two elements carrying the same class render identically wherever they
sit.

The `surface` and `component` split from the token tree runs through the
classes as well, with surface type sized against prose and component type
against controls.

## Surface roles

Sized roles are `type-surface-<role>-<size>`, and the roles that only come in
one size are `type-surface-<role>`.

::component-preview{name="TypographySurfacePreview"}
```html
<h1 class="type-surface-title-md">Page title</h1>
<p class="type-surface-body-md">Body copy.</p>
<p class="type-surface-footnote">Footnote.</p>
```
::

::docs-table
---
columns:
  - label: Role
  - label: Sizes
rows:
  - items:
      - label: display
      - label: '`sm` `md` `lg` `xl`'
        plaintext: true
  - items:
      - label: title
      - label: '`sm` `md` `lg` `xl`'
        plaintext: true
  - items:
      - label: subtitle
      - label: '`sm` `md` `lg` `xl`'
        plaintext: true
  - items:
      - label: callout
      - label: '`sm` `md` `lg` `xl`'
        plaintext: true
  - items:
      - label: body
      - label: '`sm` `md`'
        plaintext: true
  - items:
      - label: caption
      - label: none
        plaintext: true
  - items:
      - label: footnote
      - label: none
        plaintext: true
  - items:
      - label: code
      - label: none
        plaintext: true
---
::

## Component sizes

Component type is `type-component-<size>`, running from `5xs` to `5xl` and
sized against controls rather than prose.

::component-preview{name="TypographyComponentPreview"}
```html
<span class="type-component-sm">Save changes</span>
<span class="type-component-md -strong">Save changes</span>
<span class="type-component-md -number">1234567890</span>
```
::

## Modifier classes

Weight and family variations are chained onto the role class rather than
replacing it.

::docs-table
---
columns:
  - label: Modifier
  - label: Applies to
  - label: Effect
rows:
  - items:
      - label: '-strong'
      - label: every role except type-surface-code
        plaintext: true
      - label: The role’s strong weight.
        plaintext: true
  - items:
      - label: '-alt'
      - label: type-component-*
      - label: The alternate component weight.
        plaintext: true
  - items:
      - label: '-number'
      - label: type-component-*
      - label: The numeric font family, for tabular digits.
        plaintext: true
  - items:
      - label: '-short'
      - label: type-surface-body-*, type-surface-callout-*
      - label: The short line height, for headings set in body type.
        plaintext: true
---
::

```html
<p class="type-surface-body-sm -strong">A strong lead sentence.</p>
```

A modifier only changes the one property it names, so `-strong` resolves
against whichever role it is attached to: `type-surface-title-md -strong` takes
the title role’s strong weight and `type-surface-body-sm -strong` takes the
body role’s, and a theme is free to set the two apart.

## Limitations

A `type-*` class sets the whole stack at once, and there is no `font-*`,
`text-<size>`, `leading-*` or `tracking-*` escape hatch into the token values.
Mixing a title’s size with a body’s line height is the drift the roles exist to
prevent. The cost is that a real exception has to be written as plain CSS, which
we think is the right place for it to be visible.

Tailwind’s own `text-left`, `truncate` and friends are untouched, since we only
own the type roles.
