Prose
tier 2 — classes
Long-form text the app did not author — a release note, a knowledge-base article, an
e-mail body — and a value the reader is not allowed to see. Rendered Markdown has its own
class, .markdown-body, and looks identical.
Prose
.prose normalises headings, paragraphs, lists, quotes, code and links onto the
tokens, for HTML that did not come from Markdown. The 72-character measure sits on
the element carrying the class, so where the prose is a panel —
class="card-body prose" — set --prose-measure: none on the
box and put the class on an inner wrapper.
Release 0.4.0
This release adds the overlay family and the collection classes. Nothing was renamed, so an upgrade needs no app changes.
Every class name added is listed below, so you can grep your own stylesheets before bumping.
.drawerand.sheet.palette,.spotlight-hole
An image inside prose is capped at the measure and rounded by
.prose img, so an article body cannot be widened by whatever the author
pasted into it.
<div class="prose">
<h2>Release 0.4.0</h2>
<p>
This release adds the overlay family and the collection classes. Nothing was renamed,
so an upgrade needs no app changes.
</p>
<blockquote>Every class name added is listed below, so you can grep your own
stylesheets before bumping.</blockquote>
<ul>
<li><code>.drawer</code> and <code>.sheet</code></li>
<li><code>.palette</code>, <code>.spotlight-hole</code></li>
</ul>
<figure class="media-figure">
<div class="media-frame media-frame--wide media-frame--cover">
<img src="https://images.unsplash.com/photo-1627309366653-2dedc084cdf1?w=840&h=360&fit=crop&q=70&auto=format"
width="840" height="360" loading="lazy"
alt="A warehouse interior: orange and blue racking down one side of an open floor" />
</div>
<figcaption>The floor the new overlay classes were built for. Photo by Jacques Dillies on Unsplash.</figcaption>
</figure>
<p>
An image inside prose is capped at the measure and rounded by
<code>.prose img</code>, so an article body cannot be widened by whatever the author
pasted into it.
</p>
</div>
HTML from somewhere else
.prose--foreign adds containment on top of
.prose's typography: what a 3000px-wide table, an unbroken 400-character URL or
a 4000px image does to the card it landed in. Add it to anything sanitized rather than
authored — a ticketing system's journal entry, a forwarded mail body, a CMS field — and note
that it contains but does not sanitize: the same server-side pass has to add
tabindex="0" to a table that scrolls, or a keyboard cannot reach the off-screen
columns, and role="table" to put back the role
display: block drops.
Reply received from the customer, forwarded from https://helpdesk.example.gov/ticket/4182/comments?thread=a7f3c1e9b2&expand=attachments&from=notification
| Host | Mailbox | Database | Quota | Used | Last logon |
|---|---|---|---|---|---|
| EXCH-02 | service-desk | DB-PRIMARY-01 | 50 GB | 49.8 GB | 2026-08-28 07:41 |
| EXCH-02 | invoices | DB-PRIMARY-01 | 50 GB | 31.2 GB | 2026-08-28 06:12 |
Set-Mailbox -Identity service-desk -ProhibitSendQuota 75GB -ProhibitSendReceiveQuota 80GB -IssueWarningQuota 70GB
<div class="card" style="max-width:420px">
<div class="card-body">
<div class="prose prose--foreign">
<p>
Reply received from the customer, forwarded from
https://helpdesk.example.gov/ticket/4182/comments?thread=a7f3c1e9b2&expand=attachments&from=notification
</p>
<!-- tabindex and role are on the table because the CONTAINMENT costs both:
a scroll container needs keyboard access, and display: block drops a
table's own role. Foreign HTML arrives without either, so the same
sanitizer that cleans it adds them. -->
<table tabindex="0" role="table" aria-label="Mailbox quotas on EXCH-02">
<thead>
<tr><th>Host</th><th>Mailbox</th><th>Database</th><th>Quota</th><th>Used</th><th>Last logon</th></tr>
</thead>
<tbody>
<tr><td>EXCH-02</td><td>service-desk</td><td>DB-PRIMARY-01</td><td>50 GB</td><td>49.8 GB</td><td>2026-08-28 07:41</td></tr>
<tr><td>EXCH-02</td><td>invoices</td><td>DB-PRIMARY-01</td><td>50 GB</td><td>31.2 GB</td><td>2026-08-28 06:12</td></tr>
</tbody>
</table>
<pre>Set-Mailbox -Identity service-desk -ProhibitSendQuota 75GB -ProhibitSendReceiveQuota 80GB -IssueWarningQuota 70GB</pre>
</div>
</div>
</div>
Redacted values
A value deliberately withheld — a secret, a masked identifier, a field the reader's role cannot see. It must not merely look hidden: this class marks a placeholder the server sent in place of the value, so if the real text is in the HTML it is not redacted, whatever it looks like.
<div class="card" style="max-width:420px">
<div class="card-body">
<div class="kv"><span class="k">Client ID</span><span class="v">orders-console-01</span></div>
<div class="kv">
<span class="k">Client secret</span>
<span class="redacted"><i class="ri-eye-off-line"></i> not shown</span>
</div>
<div class="kv">
<span class="k">Salary band</span>
<span class="redacted"><i class="ri-lock-line"></i> requires HR role</span>
</div>
</div>
</div>