# Minimum Readable Body Size

**MUST** · **ID:** `content-impeccable-tiny-text` · **Category:** content
**Source:** [impeccable](https://impeccable.style/)
**Interactive version:** https://ui-guides-agent-rules.netlify.app/principles/content-impeccable-tiny-text

> MUST: Set prose at 14px minimum, 16px ideally, in `rem` so browser font settings still apply — anything under 12px on an element with more than 20 characters of text is a bug. UI chrome (buttons, links, labels, nav, badges, code, captions) is exempt.

Set prose at 14px minimum and 16px ideally, in rem so browser font settings still apply

impeccable's detector fires on font-size below 12px only where an element carries more than 20 characters of direct text, and it explicitly excludes UI chrome: buttons, links, labels, nav, footers, badges, code, captions, and uppercase labels. That exclusion is the whole point. A 10px button label is fine; a 10px paragraph of terms of service is the bug. Pair the size floor with rem or em units rather than px, so a reader who raises their default browser font size actually gets larger text.

## Bad — do not do this

`content-impeccable-tiny-text-bad`

```tsx
export function ImpeccableTinyTextBad() {
  return (
    <div className="space-y-3">
      <div className="rounded-lg border border-border bg-card p-4">
        <h4 className="mb-2 text-base font-semibold text-foreground">Terms of service</h4>

        {/* The bug: 10px PROSE. 60+ characters of running text nobody can read. */}
        <p className="text-[10px] leading-[1.5] text-muted-foreground">
          By creating an account you agree that we may store your project metadata for as long as
          the account exists, that build logs are retained for 30 days, and that usage above the
          included quota is billed at the end of each calendar month. You can export or delete your
          data at any time from the account settings page.
        </p>

        <div className="mt-3 flex items-center gap-2">
          {/* Also 10px — but this is a UI chrome label, not prose. Same size, different rule. */}
          <button className="rounded-md bg-primary px-3 py-1.5 text-[10px] text-primary-foreground">
            Accept
          </button>
          <span className="text-[10px] text-muted-foreground">Updated Mar 2026</span>
        </div>
      </div>

      <p className="text-xs text-error">
        Both the paragraph and the button label are 10px, but only the paragraph is the bug. The
        detector fires on font-size &lt; 12px on an element carrying more than 20 characters of
        direct prose — it skips buttons, links, labels, nav, footers, badges, code, and captions. A
        wall of 10px running text is unreadable on a high-DPI screen; a 10px button label is not
        prose.
      </p>
    </div>
  );
}
```

## Good — do this

`content-impeccable-tiny-text-good`

```tsx
export function ImpeccableTinyTextGood() {
  return (
    <div className="space-y-3">
      <div className="rounded-lg border border-border bg-card p-4">
        <h4 className="mb-2 text-base font-semibold text-foreground">Terms of service</h4>

        {/* Prose at 1rem — scales with the user's browser font-size setting */}
        <p className="text-[1rem] leading-[1.6] text-muted-foreground">
          By creating an account you agree that we may store your project metadata for as long as
          the account exists, that build logs are retained for 30 days, and that usage above the
          included quota is billed at the end of each calendar month. You can export or delete your
          data at any time from the account settings page.
        </p>

        <div className="mt-3 flex items-center gap-2">
          {/* Still small — a UI chrome label is allowed to be, and the detector excludes it */}
          <button className="rounded-md bg-primary px-3 py-1.5 text-[0.8125rem] text-primary-foreground">
            Accept
          </button>
          <span className="text-[0.6875rem] uppercase tracking-[0.08em] text-muted-foreground">
            Updated Mar 2026
          </span>
        </div>
      </div>

      <p className="text-xs text-success">
        The prose moves to 1rem (16px, the ideal; 14px is the floor) and stays in rem so a reader
        who raises their browser font size gets bigger text. The timestamp stays at 0.6875rem on
        purpose — the rule is about body content, not chrome, so short uppercase labels and button
        text keep their small size.
      </p>
    </div>
  );
}
```

## References

- [impeccable](https://impeccable.style/)
- [MDN: font-size](https://developer.mozilla.org/en-US/docs/Web/CSS/font-size)
- [WCAG 1.4.4: Resize text](https://www.w3.org/WAI/WCAG21/Understanding/resize-text.html)
