# Padding Must Scale With Type

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

> MUST: Scale padding inside any bordered, outlined, or filled container from its font size: vertical >= `max(4px, fontSize * 0.3)` and horizontal >= `max(8px, fontSize * 0.5)` — at least 8px, ideally 12–16px. Also catch the `padding: 28px 0 0` shorthand bug, where the sides get quietly zeroed and text sits flush against the border.

Derive container padding from the font size instead of hardcoding a value that 20px text will burst

The detector is thresholded, not a matter of taste: inside any container with a visible boundary it requires vertical padding >= max(4px, fontSize * 0.3) and horizontal padding >= max(8px, fontSize * 0.5). Horizontal gets the bigger multiplier because line-height already supplies vertical breathing room, while nothing pads the sides of a glyph. It catches a second shape too: a wrapper with a visible boundary and <= 2px of padding whose text children sit flush against the border — the classic `padding: 28px 0 0` shorthand bug, where someone set the top and quietly zeroed the sides. This is the thresholded sibling of the vague "Crowded Elements" (Rams) principle in this corpus: that one says give elements room, this one says exactly how much.

## Bad — do not do this

`layout-impeccable-cramped-padding-bad`

```tsx
/**
 * Bad: padding hardcoded independently of the type size.
 *
 * 1. The alert renders 20px text inside `padding: 2px 4px`. The threshold is
 *    vertical >= max(4, 20 * 0.3) = 6px and horizontal >= max(8, 20 * 0.5) = 10px.
 *    Both fail — the glyphs press against the border.
 * 2. The section below uses the classic `padding: 28px 0 0` shorthand bug:
 *    someone set the top and silently zeroed the sides, so the heading and the
 *    body text sit flush against the left border.
 */
export function ImpeccableCrampedPaddingBad() {
  return (
    <div className="w-full max-w-sm space-y-4">
      {/* 20px text, 2px/4px padding */}
      <div
        className="rounded-lg border border-error bg-muted text-foreground"
        style={{ fontSize: '20px', lineHeight: '24px', padding: '2px 4px' }}
      >
        Payment failed
      </div>

      {/* padding: 28px 0 0 — sides zeroed */}
      <div
        className="rounded-lg border border-border bg-card"
        style={{ padding: '28px 0 0' }}
      >
        <h4 className="text-sm font-semibold text-foreground">Retry payment</h4>
        <p className="mt-1 pb-4 text-xs text-muted-foreground">
          Your card was declined by the issuing bank.
        </p>
      </div>

      <p className="text-xs text-error">
        20px text in <code>padding: 2px 4px</code> needs at least 6px vertical and 10px horizontal
        &mdash; it has neither. Below it, <code>padding: 28px 0 0</code> leaves the text flush
        against the left border.
      </p>
    </div>
  );
}
```

## Good — do this

`layout-impeccable-cramped-padding-good`

```tsx
/**
 * Good: padding derived from the font size, not guessed.
 *
 * For 20px text the floor is vertical max(4, 20 * 0.3) = 6px and horizontal
 * max(8, 20 * 0.5) = 10px. We clear it comfortably with 12px / 16px — inside
 * impeccable's "ideally 12–16px" band. The second container gets padding on
 * every side, so nothing touches the boundary.
 */
export function ImpeccableCrampedPaddingGood() {
  const fontSize = 20;
  const padY = Math.max(4, fontSize * 0.3); // 6px floor -> we spend 12px
  const padX = Math.max(8, fontSize * 0.5); // 10px floor -> we spend 16px

  return (
    <div className="w-full max-w-sm space-y-4">
      <div
        className="rounded-lg border border-border bg-muted text-foreground"
        style={{
          fontSize: `${fontSize}px`,
          lineHeight: '24px',
          padding: `${padY * 2}px ${padX * 1.6}px`,
        }}
      >
        Payment failed
      </div>

      {/* Padding on all four sides — no zeroed edges */}
      <div className="rounded-lg border border-border bg-card p-4">
        <h4 className="text-sm font-semibold text-foreground">Retry payment</h4>
        <p className="mt-1 text-xs text-muted-foreground">
          Your card was declined by the issuing bank.
        </p>
      </div>

      <p className="text-xs text-success">
        Padding scales with type: 20px text gets {padY * 2}px vertical / {padX * 1.6}px horizontal,
        clearing the {padY}px &times; {padX}px floor. The section below is padded on all four sides.
      </p>
    </div>
  );
}
```

## References

- [impeccable.style](https://impeccable.style/)
- [MDN — padding](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/padding)
