Typography

Use pre-composed text styles. Let fluid type handle responsiveness. Pair semantic colors with semantic HTML.

Two font families: Intermission (sans-serif, via font-sans) and IBM Plex Mono (monospace, via font-mono).

Type scale

Sizes text-lg and above use clamp() for fluid scaling between viewport widths. No manual breakpoint overrides needed.

xs

The quick brown fox

12px

sm

The quick brown fox

14px

base

The quick brown fox

16px

lg

The quick brown fox

18-20px

xl

The quick brown fox

20-24px

2xl

The quick brown fox

24-32px

3xl

The quick brown fox

28-40px

4xl

The quick brown fox

32-48px

5xl

The quick brown fox

36-64px

Text style utilities

Pre-composed utilities that combine font size, weight, line height, and letter spacing. Two contexts: UI for app interfaces and Prose for long-form content.

UI display styles

Compact headings for dashboards, settings, navigation. Tighter line height and tracking.

ui-1

Bold (700)

text-display-ui-1

ui-2

Bold (700)

text-display-ui-2

ui-3

Bold (700)

text-display-ui-3

ui-4

Bold (700)

text-display-ui-4

ui-5

Semibold (600)

text-display-ui-5

ui-6

Semibold (600)

text-display-ui-6

Prose display styles

Larger, heavier headings for articles, marketing pages, rich content. Designed for reading.

prose-1

Black (900)

text-display-prose-1

prose-2

Extrabold (800)

text-display-prose-2

prose-3

Bold (700)

text-display-prose-3

prose-4

Bold (700)

text-display-prose-4

prose-5

Bold (700)

text-display-prose-5

prose-6

Bold (700)

text-display-prose-6

Body text styles

text-ui

App interface text with tighter line height (1.35). Default on body — no class needed for standard UI text.

Base size, 1.35 line height, -0.01em tracking

text-prose

Long-form content with more generous line height (1.5). Better for extended reading like articles and documentation.

Base size, 1.5 line height, -0.01em tracking

text-ui-meta

Secondary UI text like timestamps, counts, and helper text.

Small size, 1.35 line height

text-code

const roadie = 'monospaced code text'

Small size, 1.625 line height, monospace font

Semantic text colors

Use semantic color utilities instead of raw color values. They adapt to intents, themes, and dark mode automatically.

text-strong — headings, emphasis, high contrast

text-normal — body text (inherited from body reset)

text-subtle — secondary text, descriptions

text-subtler — meta text, timestamps, hints

Usage

Headings

Use raw heading elements with a display style utility and text-strong. Match semantic level (h1-h6) to document structure, visual style to context.

<div className="grid gap-2">
  <h1 className="text-display-ui-1 text-strong">Page title</h1>
  <h2 className="text-display-ui-3 text-strong">Section</h2>
  <h3 className="text-display-ui-5 text-strong">Subsection</h3>
</div>

Body text

Body inherits text-ui from the reset. Just use <p> elements with semantic color classes.

<div className="grid gap-2">
  <p>Default body text — no class needed</p>
  <p className="text-subtle">Secondary text</p>
  <p className="text-sm text-subtler">Meta / hint text</p>
  <p className="text-strong">Emphasised text</p>
</div>

Prose content

Wrap CMS output, markdown, or user-generated content in <Prose> for automatic typography and spacing.

<Prose>
  <h2>Article heading</h2>
  <p>
    Body paragraph with <strong>bold</strong> and{' '}
    <a href="#">links</a>. The Prose component handles spacing,
    list styles, and element typography.
  </p>
  <ul>
    <li>List item one</li>
    <li>List item two</li>
  </ul>
</Prose>

Line height and tracking

Semantic tokens for consistent rhythm. Text style utilities set these automatically — use individual tokens only for custom compositions.

ContextLine heightLetter spacing
display1.2-0.02em
ui1.35-0.01em
prose1.5-0.01em
code1.6250em

Guidelines

Use text style utilities

Text style utilities combine size, weight, line height, and letter spacing into a single class. Raw Tailwind size classes miss the other properties.

Section title

Body text inherits defaults

Secondary text

<h2 className="text-display-ui-3 text-strong">Section title</h2>
<p>Body text inherits defaults</p>
<p className="text-sm text-subtle">Secondary text</p>

Do

Use pre-composed utilities — they set all typographic properties at once.

Section title

Body text

Secondary text

<h2 className="text-2xl font-bold">Section title</h2>
<p>Body text</p>
<p className="text-sm text-gray-500">Secondary text</p>

Don’t

Don't use raw size + weight classes — they miss line height and letter spacing.

Use semantic text colors

Semantic colors like text-subtle adapt to intents, themes, and dark mode. Raw color classes break with context changes.

Strong text

Default text

Subtle text

Subtler text

<p className="text-strong">Strong text</p>
<p className="text-normal">Default text</p>
<p className="text-subtle">Subtle text</p>
<p className="text-subtler">Subtler text</p>

Do

Semantic colors adapt to the current intent and theme automatically.

Bold gray 900

Gray 700

Gray 500

Gray 400

<p className="font-bold text-gray-900">Bold gray 900</p>
<p className="text-gray-700">Gray 700</p>
<p className="text-gray-500">Gray 500</p>
<p className="text-gray-400">Gray 400</p>

Don’t

Don't hardcode color values — they won't respond to intent or dark mode.

Match context to content type

UI styles are compact for app interfaces. Prose styles are larger for long-form reading. Mixing them creates visual inconsistency.

Dashboard

Recent orders

3 orders in the last 24 hours

<h3 className="text-display-ui-4 text-strong">Recent orders</h3>
<p className="text-sm text-subtle">3 orders in the last 24 hours</p>

Do

UI headings for dashboards, prose headings for articles.

Dashboard

Recent orders

3 orders in the last 24 hours

<h3 className="text-display-prose-4 text-strong">Recent orders</h3>
<p className="text-sm text-subtle">3 orders in the last 24 hours</p>

Don’t

Don't use prose display styles in app UI — they're too large and heavy.

Use semantic HTML elements

Use the right element for the content type. Heading elements establish document structure for accessibility and SEO.

<h2 className="text-display-ui-3 text-strong">
Section title
</h2>
<p className="text-subtle">
Description text
</p>

Do

Use headings for headings, paragraphs for text, spans for inline fragments.
<div className="text-display-ui-3 text-strong">
Section title
</div>
<div className="text-subtle">
Description text
</div>

Don’t

Don't use divs for text content — screen readers can't identify the structure.

Let fluid type handle responsiveness

Text style utilities already use clamp() for fluid scaling. Adding breakpoint overrides for font size fights the system.

{/* Automatically fluid */}
<h1 className="text-display-ui-1 text-strong">
Dashboard
</h1>

Do

Fluid type scales smoothly across all viewport widths.
{/* Fighting the fluid scale */}
<h1 className="text-xl md:text-2xl lg:text-4xl">
Dashboard
</h1>

Don’t

Don't add manual breakpoints for font size — it creates jarring jumps.

Maintain heading hierarchy

Heading levels should follow document structure (h1 → h2 → h3). Visual weight is controlled by the display utility, not the heading level.

<h1 className="text-display-ui-1 ...">Page</h1>
<h2 className="text-display-ui-3 ...">Section</h2>
<h3 className="text-display-ui-5 ...">Sub</h3>

Do

Semantic levels follow structure. Visual style is independent.
<h1 className="text-display-ui-1 ...">Page</h1>
{/* Skipped h2! */}
<h4 className="text-display-ui-5 ...">Sub</h4>

Don’t

Don't skip heading levels for visual effect.

Use Prose for rich content

The <Prose> component styles nested HTML for CMS output, markdown, or user-generated content. It handles spacing, list markers, and element typography.

<Prose>
<h2>Title</h2>
<p>Paragraph with <a href="#">link</a></p>
<ul><li>Item</li></ul>
</Prose>

Do

Prose handles all child element styling automatically.
<div>
<h2 className="text-2xl mb-4">Title</h2>
<p className="mb-2 leading-6">Text</p>
<ul className="list-disc pl-4">...</ul>
</div>

Don’t

Don't manually style every element in user content.

Semantic elements guide

ElementWhen to useExample
<h1>-<h6>Section headingstext-display-ui-3 text-strong
<p>Body text, descriptionstext-subtle
<span>Inline text fragmentstext-sm text-subtler
<strong>Important texttext-strong
<em>Emphasis / stress(italic by default)
<Code>Inline code, tokens, commands<Code>bg-normal</Code>
<Prose>CMS / markdown content<Prose size="md">...</Prose>