# Body Text Never Touches the Viewport Edge

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

> MUST: Never let a paragraph or list item land within 16px of the left or right viewport edge — give the wrapping container at least 16px (ideally 24–32px) of horizontal padding, or a `max-width` plus `mx-auto` once there is room for one.

Give body copy a gutter — never let paragraphs bleed flush against the left or right edge of the screen

This is distinct from cramped padding: there the container exists and is too tight, here the container is missing entirely. The detector flags a <p> or <li> with more than 40 characters of text, wider than 50% of the viewport, whose left edge sits less than 16px from the viewport edge (or whose right edge is within 16px of the far side). Text that runs into the physical edge of the screen has no margin for the eye to return to on each line wrap, and on a phone it collides with the rounded corners and the palm holding the device. The fix is at least 16px — ideally 24–32px — of horizontal padding on a wrapping container, or a max-width plus mx-auto once there is room for one.

## Bad — do not do this

`layout-impeccable-body-text-viewport-edge-bad`

```tsx
/**
 * Bad: the article is rendered straight into the (simulated) mobile viewport
 * with no wrapping container, so every paragraph runs flush into both edges.
 * The detector fires: a <p> over 40 characters, wider than 50% of the viewport,
 * with its left edge less than 16px from the viewport edge. Gutter: 0px.
 */
export function ImpeccableBodyTextViewportEdgeBad() {
  return (
    <div className="w-full max-w-sm space-y-4">
      {/* Simulated phone viewport */}
      <div className="mx-auto w-[280px] overflow-hidden rounded-2xl border border-border bg-card">
        <div className="border-b border-border bg-muted py-2 text-center text-[10px] text-muted-foreground">
          viewport &mdash; 280px
        </div>

        {/* No horizontal padding anywhere: text meets glass */}
        <div className="py-4">
          <h4 className="text-sm font-semibold text-foreground">Shipping the redesign</h4>
          <p className="mt-2 text-xs leading-relaxed text-foreground">
            We rebuilt the dashboard around a single column so the primary action is always the
            first thing you reach, on any screen size.
          </p>
          <p className="mt-2 text-xs leading-relaxed text-foreground">
            Every line of this paragraph starts and ends against the edge of the screen, which is
            exactly where a thumb and a rounded corner already live.
          </p>
        </div>
      </div>

      <p className="text-xs text-error">
        0px gutter. The paragraphs bleed to both edges &mdash; the eye has no margin to return to
        on each wrap, and on a real phone the text collides with the rounded corners and the hand
        holding the device.
      </p>
    </div>
  );
}
```

## Good — do this

`layout-impeccable-body-text-viewport-edge-good`

```tsx
/**
 * Good: the same article inside a container that supplies a 24px horizontal
 * gutter (well past the 16px floor) and a max-width with mx-auto, so the
 * measure stays readable once the viewport grows past the text column.
 */
export function ImpeccableBodyTextViewportEdgeGood() {
  return (
    <div className="w-full max-w-sm space-y-4">
      {/* Same simulated phone viewport */}
      <div className="mx-auto w-[280px] overflow-hidden rounded-2xl border border-border bg-card">
        <div className="border-b border-border bg-muted py-2 text-center text-[10px] text-muted-foreground">
          viewport &mdash; 280px
        </div>

        {/* px-6 = 24px gutter, plus a max-width + mx-auto for wider screens */}
        <div className="mx-auto max-w-[65ch] px-6 py-4">
          <h4 className="text-sm font-semibold text-foreground">Shipping the redesign</h4>
          <p className="mt-2 text-xs leading-relaxed text-foreground">
            We rebuilt the dashboard around a single column so the primary action is always the
            first thing you reach, on any screen size.
          </p>
          <p className="mt-2 text-xs leading-relaxed text-foreground">
            Every line of this paragraph has room to breathe on both sides, so the eye lands
            cleanly at the start of the next one.
          </p>
        </div>
      </div>

      <p className="text-xs text-success">
        24px gutter on both sides &mdash; past the 16px floor, inside the 24&ndash;32px sweet spot
        &mdash; plus <code>max-width</code> and <code>mx-auto</code> so the measure holds when the
        viewport gets wider.
      </p>
    </div>
  );
}
```

## References

- [impeccable.style](https://impeccable.style/)
- [MDN — max-width](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/max-width)
- [Practical Typography — line length](https://practicaltypography.com/line-length.html)
