# Prose

> Typography styling for a block of rich, CMS, or markdown HTML you don't control element by element.

URL: https://apogee.avaui.dev/docs/prose
Last updated: 2026-10-15

Typography styling for a block of rich, CMS, or markdown HTML you don't control element by element.

Last updated October 15, 2026

```astro
<Prose>
<h2>Getting started</h2>
<p>Prose styles any block of rich or CMS-authored HTML you don't hand-style
element by element — token-driven, so it themes with everything else.</p>
<ul>
  <li>Works with <code>set:html</code> or plain children</li>
  <li>Links, lists, quotes, and code all get consistent spacing</li>
</ul>
</Prose>
```

## Add

```sh
npx @ava-ui/apogee add prose
```

No Apogee component dependencies, no icons. Zero JS — a global, `.apogee-prose`\-scoped CSS layer.

## Usage

```astro
---
import Prose from '@/components/apogee/Prose/Prose.astro'
---
<Prose set:html={article.body} />
```

## API

`@composable` — exposed to Content Editors in AVA. Accepts any other attribute (e.g. `set:html`, `id`), which passes through to the wrapper `<div>`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `class` | `string` | — | Extra classes on the wrapper, merged last. |

## States

Static: no interactive states. Links inside thicken their underline on hover.

## Examples

Every element a page can contain, styled by Prose:

```astro
<Prose>…every element…</Prose>
```

Trusted/sanitized CMS or markdown HTML:

```astro
<Prose set:html={renderedMarkdown} />
```

Authored inline as children instead:

```astro
<Prose>
  <h2>Release notes</h2>
  <p>What changed in this version.</p>
</Prose>
```

The styled element catalogue — headings, links, emphasis, lists, quotes, code:

```astro
<Prose>
<h2>Heading two</h2>
<h3>Heading three</h3>
<p>A paragraph with a <a href="#">link</a> and <strong>bold text</strong>.</p>
<ul>
  <li>Unordered item</li>
  <li>Another item</li>
</ul>
<ol>
  <li>Ordered item</li>
  <li>Another item</li>
</ol>
<blockquote>A quoted aside.</blockquote>
<pre><code>const x = 1</code></pre>
<hr />
</Prose>
```

### Opting a block out

Wrap a callout or a card in `.not-prose` and Prose leaves it alone; style it with utilities:

```astro
<Prose>
<p>Body text.</p>
<div class="not-prose mt-8 rounded-2xl bg-neutral-faded p-6">
  <h2 class="text-xl font-semibold">Conclusion</h2>
  <p class="mt-2 text-neutral-faded">Kept out of the prose styles.</p>
</div>
</Prose>
```

## Accessibility

-   Native semantics, no extra ARIA needed — Prose is a CSS layer over your own markup; semantics come entirely from the HTML you put inside (or the CMS HTML you render).
-   Using `set:html`: sanitize the source yourself — Prose only styles, it never sanitizes.

## Tokens

| Token | Used for |
| --- | --- |
| `--foreground-neutral` | Body + heading text |
| `--foreground-primary` | Link colour and hover |
| `--foreground-neutral-faded` | List marker colour, blockquote text |
| `--border-primary` | Blockquote rule |
| `--border-neutral` | `<hr>`, table rules, `kbd` outline |
| `--background-neutral-faded` | Inline `code` and `pre` background |
| `--background-elevation-raised` | `kbd` background |
| `--background-warning-faded` | `mark` highlight |
| `--font-serif` / `--font-mono` | Blockquote / code and `kbd` |
| `--radius-sm` | Inline `code`, `kbd` and `mark` corners |
| `--radius-lg` / `--radius-md` | `pre` / `img`, `video` and `iframe` corners |

## Do / Don’t

-   **Do** use it for any block of HTML you don’t style element by element — CMS output, rendered markdown, long-form copy.
-   **Do** sanitize untrusted HTML before `set:html` — Prose doesn’t clean input, it only styles it.
-   **Don’t** reach for Prose to style one isolated element (a lone `<p>` or `<a>`) — style it directly instead.
-   **Don’t** nest interactive app UI (buttons, forms) inside — it’s a typography layer, not a layout system.

## Content

-   No wording rules of its own — copy follows whatever produced it (CMS, markdown, hand-authored). Keep headings short enough that the built-in `text-wrap: balance` reads well.

## Related

[

TextBody copy with a size scale and semantic colours. Renders p, span, or div.

](https://apogee.avaui.dev/docs/text)[

HeadingA semantic, fluid-sized heading — pick the tag with \`as\`, the visual size with \`size\`.

](https://apogee.avaui.dev/docs/heading)[

BlockquoteA pull quote with optional attribution. Use to set a quoted passage apart from body copy.

](https://apogee.avaui.dev/docs/blockquote)[

CodeInline code or a code block with build-time highlighting, line numbers, a copy button and a collapsible long view.

](https://apogee.avaui.dev/docs/code)
