Typography

How prose, the Tailwind scale, and global styles set all text.

index.ts sourceglobal.css sourcetailwind.config.js source

Prose and not-prose

Prose styles long-form content by element. ReaderView, Viewer, Editor, and Explorer wrap their content in getProseClasses(size), and the typography plugin then styles every plain heading, paragraph, list, link, code, and table inside it. Everywhere else, classes set the text. When you put UI inside prose, such as a card or a demo, wrap it in not-prose and size its text with the classes in the next section.

Inside prose

Plain elements get a size, spacing, and color. A link is underlined, and code becomes a chip.

  • Lists get bullets.
  • No classes are needed.

Inside not-prose

The same elements get only the site's global rules. A link has no underline.

  • Lists have no bullets.
  • Every size comes from a class.

UI text sizes

Choose the size from the job of the text, not from how large you want it. Each row names one job and the components that use it. When a component sets the text, such as Card.Title or Field.Description, use the component and do not add a size class. Each size sets its own line height, shown after the size. Use only these sizes. The 11, 13, and 15 steps are project tokens that fill gaps in the Tailwind scale, so write text-13, not text-[13px]. Older code outside the UI library still uses the arbitrary values. Use the tokens in new code.

text-2xl font-bold24/32Section headings in UI outside the reader, such as a dashboard header.
Create your first insight
text-xl font-bold20/28A heading over a group of cards or a settings section.
Filter by property
text-lg18/28Lead text: one or two sentences under a heading. EmptyState titles add font-semibold.
PostHog is the single platform to analyze, test, and ship.
text-base font-bold16/24Dialog titles. Accordion triggers and panels use text-base at the normal weight.
Delete this insight?
text-15 font-semibold15/22.5Card and toast titles. Popover and fieldset titles use it with font-bold.
Weekly product report
text-1515/22.5Body text in a card or a panel, tabs, and lg controls. It matches the body text of the reader.
Capture events, then build funnels and trends from them.
text-sm14/20The default for form controls and lists: inputs, select and combobox options, table cells, and dialog descriptions. Labels add font-semibold.
Applies to all environments in this project.
text-13 text-secondary13/18Supporting text: field descriptions and errors, tooltips, card meta, status bars, and table column headings. Menu items and md buttons use text-13 in text-primary.
Updated 3 minutes ago
text-xs12/16md badges and sm buttons only.
Beta
text-11 font-semibold uppercase11/14Tiny labels: sm badges, sm field chips, menu group labels, and sm Kbd. Menu group labels add tracking-wide and text-muted.
Recent
font-code text-1313/18Code, IDs, and property values in UI, such as card meta. For code inside a sentence, use Snippet.Inline, which sizes itself to the text around it.
posthog.capture('signed_up')

Headings outside prose

Outside prose, a heading has no size of its own. Tailwind's base styles give it the size of the text around it, as the last row shows. Always give it a size class from the table above. Choose the level from the page outline and the size from the job. On reader pages, global.css makes every h4 18px, and a size class does not change it, so use h2 or h3 in UI.

h2 · text-2xl font-bold

Get started

h3 · text-xl font-bold

Install the snippet

h3 · text-15 font-semibold

Weekly product report

h2 · no size class

Takes the size of the text around it

Color and weight

Three colors and two weights cover all UI text. Body text uses the default weight.

Primary is for content: body text, titles, and values.

Secondary is for supporting text, such as descriptions.

Muted is for placeholders, disabled text, and quiet marks, such as separators and group labels.

Semibold is for titles, labels, and short phrases that must stand out.

Bold is for headings and dialog titles.

Usage

These are defaults, not laws. Break one when you have a good reason, or when it makes the design more cohesive or more interesting.

  • not-prose turns prose off for an element and for everything inside it. Prose cannot be turned on again inside it.
  • Some styles still reach a not-prose block. global.css makes every heading bold and gives every p a bottom margin. Text inherits the line height of the prose around it, unless a class sets one. On prose pages, every h4 is 18px and every table keeps its prose borders.
  • Add a leading-* class only to a single-line control with a fixed height, such as a button or a menu item. Text that can wrap keeps the line height of its size.
  • RoundHog has no 600 face, so font-semibold and font-bold look the same today. Still use the weight that the table names, so the text is correct if the font gets a 600 face.
  • PROSE_CORE holds the shared prose modifiers: link style, line height, heading tracking, and the h1 size. The default size is prose-sm, and global.css sets its body text to 15px. Change these in one place, not in each page.
  • Use text-3xl and larger only on marketing pages. No component uses them.
  • Text uses the site font, RoundHog, from body. Do not set a font on UI text. Use font-code for code.
  • Give each page one h1. Choose heading levels from the page outline and never skip a level. Write headings, labels, and buttons in sentence case.
  • Use tabular-nums for numbers in tables and counters.