Icon Size Guidelines for Web and Mobile UI
Exactly which icon sizes to use in every UI context — nav bars, buttons, dashboards, forms, mobile tab bars — with a size token system, spacing rules, and an interactive advisor.
Icon size is one of the most frequently inconsistent details in production UIs. A 32px icon next to a 20px icon in the same nav bar isn’t a style preference — it’s a layout error. This guide gives concrete size values for every UI context, the spacing rules that make them work, and a token system you can implement in one afternoon.
Interactive size advisor
Pick your surface and density to get the right token set for your context:
Icon Size Advisor
Pick your UI context and get a practical icon size recommendation.
The four standard size tokens
Almost every UI context maps to one of these four sizes. Using more tokens creates drift.
| Token | Size | Use case |
|---|---|---|
icon-sm | 16px | Dense data tables, inline badges, footnote icons |
icon-md | 20px | Compact navigation, form field icons, secondary actions |
icon-base | 24px | Primary nav, most buttons, standard UI controls |
icon-lg | 32px | Empty states, feature highlights, illustration-adjacent contexts |
/* Define once in your design tokens / global CSS */
:root {
--icon-sm: 16px;
--icon-md: 20px;
--icon-base: 24px;
--icon-lg: 32px;
}
// In Tailwind — map tokens to w-/h- utilities
// w-4 = 16px, w-5 = 20px, w-6 = 24px, w-8 = 32px
<Search className="w-5 h-5" /> // icon-md
<Bell className="w-6 h-6" /> // icon-base
Size by UI context
Top navigation bar
Size: 18–20px
Gap to label: 6–8px (gap-1.5 or gap-2 in Tailwind)
Top nav icons sit alongside 14–15px text labels. At 24px, they visually dominate the label. At 16px, they disappear. 18–20px matches the visual weight of the surrounding type.
<a className="flex items-center gap-2 px-3 py-2 text-sm text-gray-600">
<Home className="w-5 h-5" /> {/* 20px */}
<span>Dashboard</span>
</a>
Sidebar (expanded)
Size: 20px
Gap to label: 10–12px (gap-2.5 or gap-3)
A wider gap than top nav because sidebar items are taller and have more breathing room. 20px is large enough to read independently but doesn’t crowd the label.
Sidebar (collapsed / icon-only)
Size: 22–24px
Container: 40×40px minimum
Without a label, the icon carries all the communication weight. Bump to 22–24px and ensure the tap/click target is at least 40×40px.
These icons at 22px — the right size for a collapsed sidebar.
Button icons
Size: font-size * 1.1–1.2 (cap-height match)
Common: 16px with text-xs, 18px with text-sm, 20px with text-base
Gap: 6–8px
The icon should visually match the cap height of the button label, not the full line height. A text-sm (14px) button looks best with an 18px icon because the icon’s viewBox has internal padding that makes it visually smaller than its numeric size.
// Size reference: button size → icon size → Tailwind class
// xs button → 14px icon → w-3.5 h-3.5
// sm button → 16px icon → w-4 h-4
// md button → 18px icon → w-[18px] h-[18px]
// lg button → 20px icon → w-5 h-5
// xl button → 22px icon → w-[22px] h-[22px]
Form field icons
Leading icon (affordance): 16–18px
Trailing action icon (show/hide, clear): 18–20px
Validation icon: 16px
Form icons should be noticeably smaller than button icons to avoid competing with the input text. Inline text in most inputs is 14–16px; icons should be 16–18px.
<div className="relative">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
<input className="pl-9 pr-4 py-2 text-sm ..." placeholder="Search..." />
</div>
Dashboard / data tables
Row action icons: 16–18px
Section header icons: 20px
Chart legend icons: 14–16px
Status indicator icons: 14–16px
Dashboard contexts are information-dense. Larger icons add visual noise without information value. Keep action icons at 16–18px and use spacing (not size) to create hierarchy.
// Row actions in a table — small, tightly constrained
<div className="flex items-center gap-1">
<button aria-label="Edit" className="p-1.5 rounded hover:bg-gray-100">
<Edit className="w-4 h-4 text-gray-500" />
</button>
<button aria-label="Delete" className="p-1.5 rounded hover:bg-red-50">
<Trash2 className="w-4 h-4 text-red-500" />
</button>
</div>
Mobile bottom tab bar
Size: 24px minimum
Tab item height: 56px minimum
Label: always visible (no icon-only)
Mobile fingers, not cursors. The 44px minimum tap target rule from Apple HIG and WCAG 2.5.5 applies. A 24px icon inside a 56px tab item gives plenty of tap area.
<nav className="flex border-t">
{tabs.map(tab => (
<a key={tab.href} className="flex-1 flex flex-col items-center justify-center
min-h-[56px] gap-1 text-xs">
<tab.icon className={`w-6 h-6 ${active ? 'text-blue-600' : 'text-gray-500'}`} />
<span>{tab.label}</span>
</a>
))}
</nav>
Empty states and illustrations
Size: 48–64px (hero empty state)
Size: 32–40px (inline/card empty state)
Empty states are the one context where large icons work — they fill visual space where content should be and guide the eye to the CTA.
<div className="flex flex-col items-center gap-4 py-12 text-center">
<FolderOpen className="w-16 h-16 text-gray-300" />
<h3 className="text-lg font-medium text-gray-900">No files yet</h3>
<p className="text-sm text-gray-500">Upload your first file to get started.</p>
<Button>Upload file</Button>
</div>
Empty state icons at 48px — the right scale for full-page empty states.
Spacing rules
Icon sizing is only half the equation. Spacing matters equally.
| Context | Icon–label gap | Container padding |
|---|---|---|
| Nav item | gap-2 (8px) | px-3 py-2 |
| Button (md) | gap-2 (8px) | px-4 py-2 |
| Button (sm) | gap-1.5 (6px) | px-3 py-1.5 |
| Form field (leading) | — | pl-9 (left pad icon + gap) |
| Table action | gap-1 (4px) | p-1.5 |
| Tab bar | — | min-height: 56px |
Touch target vs icon size
On mobile, never equate icon size with tap target size. A 24px icon in a 24px container has a 24px tap target — well below the 44px minimum.
// ❌ Tap target is only 24×24px
<button><Bell className="w-6 h-6" /></button>
// ✅ Tap target is 44×44px; icon is 24px
<button className="w-11 h-11 flex items-center justify-center">
<Bell className="w-6 h-6" />
</button>
WCAG 2.5.5 (Level AA in 2.2) requires interactive targets to be at least 24×24px, with a recommended minimum of 44×44px. On mobile, 44×44px is the practical minimum for reliable tapping.
QA checklist
- No one-off icon sizes outside the four-token system (
icon-sm/md/base/lg) - Icon and text baselines align in all button and nav variants (
items-center) - Mobile touch targets are minimum 44×44px
- Icons at 16px still readable at 125% browser zoom
- All inline SVGs have
widthandheightattributes for CLS prevention
Related Reading
- SVG Icons for Navigation Menus: Sizing, Placement, and Active States
- SVG Icons for Buttons and CTAs: Placement, Sizing, and Accessibility
- SVG Icons for Dashboards
- SVG Icons in React Native & Expo: The Complete 2026 Guide
- 7 Common SVG Icon Mistakes in Production UI
- WCAG 2.2 Guidelines for Web Icons and SVGs
- Optimize SVG Icons for Faster Sites