Polish: The Last 5%

10 min

Polish: The Last 5%

The lessons before this one covered structural craft—spacing, colour, layout, interaction, accessibility, performance. This lesson covers the visual refinements that happen after everything else is right: the image outlines, shadow tuning, separator audits, and chrome hierarchy decisions that separate "done" from "polished."

These details share a property: none of them would survive an A/B test in isolation. Together, they're the reason users describe certain products as "premium" without being able to explain why.

Image outlines on white backgrounds

A photograph or screenshot dropped on a near-white background looks unanchored. The image's white edges blend into the page; the eye can't tell where the image ends and the background begins. The fix: a 1px subtle outline.

img {
  outline: 1px solid rgba(0, 0, 0, 0.1);
  outline-offset: -1px;
}

The outline is barely visible, but it's enough. The image now feels seated on the page rather than floating.

Why outline instead of border: outline doesn't take up layout space. A 1px border pushes the image inward by 1px on every side, changes the aspect ratio slightly, and triggers layout shifts when conditionally applied. outline paints over the element's edge without affecting layout.

outline-offset: -1px pulls the outline inside the image's edge. Without it, the outline sits 1px outside, colliding with neighbouring elements.

In dark mode, flip the colour:

:root           { --image-outline: rgba(0, 0, 0, 0.1); }
[data-theme="dark"] { --image-outline: rgba(255, 255, 255, 0.1); }

img { outline: 1px solid var(--image-outline); outline-offset: -1px; }

When to skip: full-bleed hero images that reach the viewport edge, images with their own dark borders or vignettes, and decorative illustrations with intentional rough edges.

Shadow refinement

Most shadows in production code are too heavy, too spread, or too uniform. A single box-shadow at one depth works for a card that sits on a flat surface; for layered UIs with multiple elevation levels, shadows need deliberate tuning.

The craft-level shadow stack uses two or three layers—a tight, dark shadow for the edge (the "contact shadow") and a wider, softer shadow for depth:

.card {
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.06),
    0 4px 12px rgba(0, 0, 0, 0.04);
}

The first layer (tight, 1–2px blur) anchors the element to the surface. The second (wide, 8–16px blur) creates ambient depth. Together, they look natural—closer to how real light behaves than a single 0 4px 8px rgba(0,0,0,0.1).

For hover elevation—cards that "lift" on hover—increase the y-offset and blur of the ambient layer while keeping the contact shadow tight:

.card:hover {
  box-shadow:
    0 1px 3px rgba(0, 0, 0, 0.08),
    0 8px 24px rgba(0, 0, 0, 0.06);
}

Dark mode shadows need different treatment. On dark backgrounds, standard rgba(0,0,0,x) shadows are often invisible—the background is already dark. Some products switch to a subtle glow (rgba(255,255,255,0.03)) or rely entirely on border contrast for elevation. Linear uses border-based elevation in dark mode; Stripe uses subtle ambient glow.

The separator audit

Every border, divider, separator, and rule on a page should justify itself. If you can remove a border without losing meaning—remove it. Borders cost visual noise; they should pay for themselves with information.

The audit process: for each border on the page, ask three questions.

  1. What information would I lose if I removed this? If "nothing meaningful," remove it.
  2. Does it read as one separator or two stacked? A card border touching a section divider, a tab underline meeting a header bottom-border—these double up and read as a single thick high-contrast line. Soften or remove one.
  3. Could a softer cue do the same job? A small spacing change, a slight background tint, or a shadow can replace many borders.

Where borders earn their keep:

  • Separation between unrelated regions (sidebar from main content).
  • Boundary on a clickable card—the user needs to see where one ends and the next begins.
  • Edge of an input field—distinguishes the typing area from the form.

Where borders are usually noise:

  • Card with shadow. The shadow already separates it; the border duplicates the work.
  • List items in a grouped, indented list. Grouping shows the relationship; per-item dividers fragment it.
  • Header with a coloured background distinct from the body. The colour change is the separator; the bottom border is noise.
  • Stacked dividers. Two separators with similar contrast next to each other read as a tangle.

Look at Linear, Things, Stripe Dashboard—notice how few borders there actually are. The screens look full because content is dense, but the line count is restrained. Most separation comes from spacing, weight contrast, or background changes.

Navigation chrome hierarchy

The chrome of an interface—the navigation bar, sidebar, breadcrumbs, tab bar—should have a clear visual hierarchy. The most important chrome (primary navigation) should be visually strongest. Secondary chrome (breadcrumbs, local tabs) should be quieter. The content area should feel like the main event, not something squeezed between competing navigation layers.

Common hierarchy mistakes:

  • Primary and secondary navigation at equal visual weight. The user can't tell which level they're looking at.
  • Navigation chrome that competes with content. Heavy borders, dark backgrounds, and large text on nav elements draw the eye away from the actual page content.
  • Inconsistent chrome across pages. The sidebar appears on some pages and not others, or changes position. The user's spatial model of the app breaks.

The fix is usually contrast reduction: lighter text, thinner borders, reduced padding on secondary chrome. The primary navigation can afford to be bold. Everything else should recede.

Common mistakes

  • Using border instead of outline for image anchoring. Layout shifts, aspect-ratio changes.
  • Heavy-handed outlines (rgba(0,0,0,0.3) or higher). Reads as a deliberate frame, not a subtle anchor.
  • Single-layer shadows with high spread. Looks like a grey box, not depth.
  • Every section gets a top and bottom border, doubling thickness at section boundaries.
  • High-contrast borders by default (1px solid #000 instead of 1px solid rgba(0,0,0,0.08)).
  • Borders that don't survive dark mode. Light borders (rgba(0,0,0,0.1)) vanish on dark backgrounds. Pair with a light-on-dark token.
  • Navigation chrome louder than page content. The user sees the frame, not the painting.