Typeset
A prose container for long-form text content. Wrap any article, blog post, or documentation block in .typeset to get sensible typography, vertical rhythm, and readable line length — no per-element tweaking needed.
Vertical Rhythm
Block siblings (p, ul, ol, blockquote, headings) are automatically spaced with --flow-space (default 0.75em). Line-height is set to 1.4 and max-width to 65ch for optimal readability.
The king, seeing how much heavier his nephew's attention was to home than his, and that all his own meaſures were fruſtrated by the unaccountable prejudice his nephew had taken againſt the unfortunate Miſs Frick, he gave it as his laſt advice.
An enumeration of all the particulars, the delivery, and the eſtate to be purchaſed, would ſwell this article to a tedious length.
Headings
h1–h4 are sized relative to each other with tighter line-height (1.2 for h1/h2, 1.33 for h3/h4). h1 gets extra top margin for section separation.
This is a level-one heading
Body text following an h1.
This is a level-two heading
Body text following an h2.
This is a level-three heading
Body text following an h3.
This is a level-four heading
Body text following an h4.
Heading Spacing Rules
Spacing between headings and body adapts to the context. A spacious 2rem gap appears before headings that follow body content, while headings after an h1 stay tightly coupled at 1rem. Body after a heading gets a close 0.5rem gap.
Page Title
Subtitled — tightly coupled to h1
Body text after a heading stays close (0.5rem). This keeps the heading visually connected to its content.
Another paragraph flowing naturally after the first. The regular rhythm between body paragraphs is 0.75em.
A New Section
When body content precedes a heading, a spacious 2rem gap is added to visually separate the new section.
Nested Subsection
Same rules apply at every heading level. Body before a heading gets breathing room; body after a heading stays close.
Lists
Unordered lists use square markers; ordered lists use decimal. Markers use the accent font and reduced opacity. List items have a small gap between them.
A paragraph before the list:
- Square markers for unordered lists
- Items have 0.25em gap between them
- Markers use the accent font at 60% opacity
A paragraph between lists:
- Decimal markers for ordered lists
- Same item spacing as unordered lists
- Also uses the accent font for markers
Lists can also be nested:
- Top-level item
- Nested item with square markers
- Another nested item
- Another top-level item
Definition Lists
dl elements use a two-column grid. Terms sit in the left column (60% opacity, no wrap) and descriptions span the right column.
- Typeset
- A prose container with sensible typography defaults.
- Flow Space
- The CSS custom property that controls vertical rhythm between block siblings.
- Ch
- A relative unit equal to the width of the "0" character, used for readable line length.
Inline Code
Inline code gets a monospace font, slightly reduced size, padding, and a subtle background. Code blocks (pre > code) are left untouched — only inline code within paragraphs or list items is styled.
The .typeset class applies a set of sensible defaults to all child elements. Use --flow-space to customize the vertical rhythm spacing.
Inline code looks distinct from body text, making it easy to spot class names like .typeset or property names like max-width inline.
Putting It All Together
A realistic example combining headings, paragraphs, lists, definition lists, and inline code — all in a single .typeset container.
On the Design of Typesetting
A brief guide to readable prose on the web
Good typography is invisible. The reader should never notice the spacing, the line length, or the font choices — they should simply read. The .typeset utility provides a set of defaults that make this possible.
Core Principles
- Line length: Capped at
65ch— roughly 65 characters per line, the sweet spot for readability. - Line height: Set to
1.4for body text, giving letters room to breathe without feeling loose. - Vertical rhythm: Block siblings are automatically spaced using the
--flow-spacecustom property.
Technical Details
- Layer
- typeset
- Selector
- :where(.typeset)
- Max Width
- 65ch
- Default Flow
- 0.75em
The :where() pseudo-class keeps specificity low, so you can override any rule without fighting selector wars. Need a different flow space? Just set --flow-space on the container or any child.