# Kill the Icon-Tile Feature Card

**NEVER** · **ID:** `aesthetics-impeccable-icon-tile-stack` · **Category:** aesthetics
**Source:** [impeccable](https://impeccable.style/)
**Interactive version:** https://ui-guides-agent-rules.netlify.app/principles/aesthetics-impeccable-icon-tile-stack

> NEVER: Stack a rounded-square icon tile above a feature heading — the tell is geometric: a heading's previous sibling measuring 32–128px on both axes, roughly square, with a visible background or border and a border-radius under half its width. Move the icon inline into the heading line, drop the container, or give the feature a real image. (A circular avatar, radius = half the width, is exempt.)

Stop stacking a rounded-square tinted icon tile above every feature heading — put the icon inline instead

The tell is geometric, so it can be detected mechanically: a previous sibling of a heading that measures 32–128px on BOTH axes, is roughly square, has a visible background or border, and has a border-radius under half its width. (A circular avatar is exempt — its radius is half the width.) That is the shape every generator reaches for, and it is why three-up feature grids from different products are indistinguishable. Break the geometry, not the icon: move the icon inline into the heading line, drop the container entirely, or let the feature carry an actual image. If the icon must sit in a box, the box has to earn it.

## Bad — do not do this

`aesthetics-icon-tile-stack-bad`

```tsx
const features = [
  { title: 'Lightning Fast', body: 'Ship in seconds with our optimized edge network.' },
  { title: 'Enterprise Ready', body: 'SOC 2 compliant with role-based access control.' },
  { title: 'Fully Extensible', body: 'Plug in your own tools with a typed SDK.' },
];

function TileGlyph() {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" className="w-6 h-6" aria-hidden="true">
      <path d="M13 2 3 14h8l-1 8 10-12h-8l1-8Z" strokeLinejoin="round" />
    </svg>
  );
}

export function IconTileStackBad() {
  return (
    <div className="w-full">
      <div className="grid grid-cols-3 gap-4">
        {features.map((f) => (
          <div key={f.title} className="rounded-2xl border border-border bg-card p-5 text-center">
            {/* The tell: a 48px rounded-square tinted icon tile, stacked directly above the heading */}
            <div className="w-12 h-12 rounded-xl bg-violet-100 text-violet-600 dark:bg-violet-500/20 dark:text-violet-300 flex items-center justify-center mx-auto mb-4">
              <TileGlyph />
            </div>
            <h3 className="text-sm font-semibold text-foreground mb-1.5">{f.title}</h3>
            <p className="text-xs text-muted-foreground leading-relaxed">{f.body}</p>
          </div>
        ))}
      </div>
      <p className="text-xs text-error mt-4">
        Three identical 48px rounded-xl tinted tiles, each stacked above an h3 — a square,
        background-filled, previous-sibling-of-a-heading box with radius under half its width.
        This is the detector's exact signature, and every generator emits it.
      </p>
    </div>
  );
}
```

## Good — do this

`aesthetics-icon-tile-stack-good`

```tsx
const features = [
  { title: 'Lightning Fast', body: 'Cold start to first byte in 40ms on the edge network.' },
  { title: 'Enterprise Ready', body: 'SOC 2 Type II, with role-based access down to the row.' },
  { title: 'Fully Extensible', body: 'A typed SDK, so your own tools are first-class.' },
];

function InlineGlyph() {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.8"
      className="w-4 h-4 shrink-0 text-muted-foreground"
      aria-hidden="true"
    >
      <path d="M13 2 3 14h8l-1 8 10-12h-8l1-8Z" strokeLinejoin="round" />
    </svg>
  );
}

export function IconTileStackGood() {
  return (
    <div className="w-full">
      <ul className="divide-y divide-border border-y border-border">
        {features.map((f) => (
          <li key={f.title} className="py-4">
            {/* Icon sits inline, inside the heading line — no container, no tile, no stack */}
            <h3 className="flex items-center gap-2 text-sm font-semibold text-foreground">
              <InlineGlyph />
              {f.title}
            </h3>
            <p className="text-xs text-muted-foreground leading-relaxed mt-1 pl-6 max-w-prose">
              {f.body}
            </p>
          </li>
        ))}
      </ul>
      <p className="text-xs text-success mt-4">
        Same three features, left-aligned. The icon is inline inside the heading, so there is no
        square, background-filled sibling above it — nothing for the detector to match, and the
        text now reads down a single edge instead of across three centered boxes.
      </p>
    </div>
  );
}
```

## References

- [impeccable](https://impeccable.style/)
- [pbakaus/impeccable](https://github.com/pbakaus/impeccable)
- [Refactoring UI](https://www.refactoringui.com/)
