Chapter 1 — Foundation · Section 05
Icons
Icons use SVG with stroke="currentColor", so they inherit their color from the CSS cascade. Always set an explicit text color class on the icon container — never rely on the ambient text-on-surface cascading through, as it will be invisible on dark token backgrounds.
Icons on Role-Pair Backgrounds
Each background token has one correct foreground. Crossing pairs is invisible. The table below shows correct vs. wrong for all three brand families.
Primary family
bg-primary
✓ PASSIcon: text-on-primary
Ratio: 9.1:1 ≥ 3:1 ✓
bg-primary
✗ FAILIcon: text-on-primary-container
Ratio: 1.2:1 < 3:1 ✗
← Wrong — see correct pairing →
bg-primary-container
✓ PASSIcon: text-on-primary-container
Ratio: 12.4:1 ≥ 3:1 ✓
bg-primary-container
✗ FAILIcon: text-on-primary
Ratio: 1.4:1 < 3:1 ✗
← Wrong — see correct pairing →
Secondary family
bg-secondary
✓ PASSIcon: text-on-secondary
Ratio: 8.4:1 ≥ 3:1 ✓
bg-secondary
✗ FAILIcon: text-on-secondary-container
Ratio: 1.1:1 < 3:1 ✗
← Wrong — see correct pairing →
bg-secondary-container
✓ PASSIcon: text-on-secondary-container
Ratio: 11.0:1 ≥ 3:1 ✓
bg-secondary-container
✗ FAILIcon: text-on-secondary
Ratio: 1.3:1 < 3:1 ✗
← Wrong — see correct pairing →
Tertiary family
bg-tertiary
✓ PASSIcon: text-on-tertiary
Ratio: 7.8:1 ≥ 3:1 ✓
bg-tertiary
✗ FAILIcon: text-on-tertiary-container
Ratio: 1.2:1 < 3:1 ✗
← Wrong — see correct pairing →
bg-tertiary-container
✓ PASSIcon: text-on-tertiary-container
Ratio: 11.8:1 ≥ 3:1 ✓
bg-tertiary-container
✗ FAILIcon: text-on-tertiary
Ratio: 1.5:1 < 3:1 ✗
← Wrong — see correct pairing →
Naked Icons on Surface Backgrounds
Icons with no background fill must pass 3:1 against the surface they sit on. When the color approaches the 3:1 floor, compensate with increased stroke weight rather than darkening the color.
on surface
text-on-surface · 16.1:1 · strokeWidth 1.5
on surface-variant (borderline)
text-on-surface-variant · 7.2:1 · strokeWidth 1.75 (compensated)
outline color (fails naked)
text-outline: ~4.6:1 — marginal · add bg fill for icon buttons
Stroke Weight Reference
| Situation | Stroke width | Visual | Notes |
|---|---|---|---|
| Icon comfortably passes 3:1 | strokeWidth=1.5 | Default — use for on-surface, on-primary, etc. | |
| Icon at 3:1 floor (borderline) | strokeWidth=1.75 | Compensate with stroke weight, not darker color | |
| Icon fails 3:1 | Change token or add bg | Use darker token OR add bg-surface-container-high fill | |
| Never use | strokeWidth=1 | Thin strokes degrade below 3:1 floor at small sizes |
Icon Sizes
12px
Inline text, chips
14px
Buttons, labels
16px
Default UI
20px
Cards, nav items
24px
Toolbar, standalone
32px
Feature icons
Icons on Gradient Backgrounds
Gradient backgrounds span tones — icons must use the lightest passing foreground. For brand gradient backgrounds, always use text-on-primary (white) since the gradient starts at the brand color (tone 40) where white passes AAA.
Primary CTA
text-on-primary · 9.1:1 AAA
Secondary CTA
text-on-primary · 8.4:1 AAA
Tertiary Deep
text-on-primary · 7.8:1 AAA
Primary Hero
text-on-primary · AAA (dark end)
Accessibility
- • All decorative icons must have
aria-hidden="true" - • Icon-only interactive elements (buttons, links) require
aria-labeldescribing the action - • Never use
stroke-width: 1— thin strokes degrade at small sizes and low DPI screens - • WCAG 1.4.11 requires 3:1 non-text contrast — all icons in interactive contexts must meet this
- • When an icon conveys meaning alongside text, the text is the accessible label — the icon is decorative