Skip to main content
Visual hierarchy is the single most important factor in making a UI feel well-designed. It refers to how important elements appear in relation to one another. When everything competes for attention equally, the interface feels noisy and chaotic. When you deliberately emphasize primary content and de-emphasize secondary content, the result is immediately more pleasing. Most interfaces have three levels: primary (what should the user notice first), secondary (supporting information), tertiary (background details). Every element must sit clearly at one level.

Size isn’t the only lever

Relying solely on font size for hierarchy leads to comically large primary content and unreadably small secondary content. Use weight and color alongside size — a semibold 18px heading communicates importance as well as a regular 24px one, and takes less space. In Sundial, the contrast ramp is the color half of this system: Two weights cover almost everything: normal (Sundial body is Inter 425) for most text, semibold (600) for headings and emphasized data. Never use weights below 400 in UI — to de-emphasize, use a lighter color or smaller size, not a thinner weight.

Don’t use gray text on colored backgrounds

Gray-on-white works because it reduces contrast. Gray on a colored background doesn’t — it just looks muddy and disabled. White at reduced opacity looks ghostly and lets the background bleed through. The right approach: pick a color from the same hue as the background — in Sundial terms, a lighter shade of the same ramp. This is exactly why AccentColors.onButton is shade 200 of the accent’s own family, not white or gray — see Accent Colors.

Emphasize by de-emphasizing

When an element won’t “pop” no matter what you do to it, the fix is usually to turn down the volume on everything else:
  • Active vs. inactive nav → soften the inactive items (Sundial’s nav bar: contrastStrong vs contrastWeak)
  • Selected vs. unselected tabs → lighten the unselected ones
  • Primary vs. secondary actions → mute the secondary button

Labels are a last resort

Label: Value for everything flattens hierarchy — label and value compete equally.
  1. You may not need one. janedoe@email.com is obviously an email; $19.99 is obviously a price.
  2. Combine into natural language. 12 left in stock beats In stock: 12.
  3. When needed, make the label secondary — smaller, lighter, or both. The data is what matters. (Sundial’s overlineSmall in contrastMedium is the house style for this — see StyledListTile.activities.)
  4. Exception: on scan-heavy spec pages where users hunt for the label itself, slightly emphasize labels over values — gently.

Separate visual hierarchy from document hierarchy

Don’t let semantic structure dictate visual weight — a section title often functions as a label, not a focal point. Style based on the role the content plays, not its heading level. Keep the semantics for accessibility; choose the text style independently.

Balance weight and contrast

Bold elements feel emphasized because they cover more surface area — and icons are surface-area-heavy by nature. An icon the same color as adjacent text will dominate it; give icons a softer color (this is why StyledTextField tints prefix icons contrastSubtle, not the text color). Similarly, when a hairline border is too subtle, make it thicker, not darker — dark borders are harsh.

Semantics are secondary to hierarchy

A destructive action is not automatically a primary action. Don’t give “Delete” a big red button just because it’s dangerous: If deleting isn’t the page’s main job, style it secondary or tertiary. In the confirmation dialog — where the destructive action IS primary — apply the bold destructive styling.