Foundations
Icons
Instagram uses a custom icon set — no public icon library matches the production vocabulary. This page documents the size scale, filled/outline grammar, colour system, touch target requirements, and the SF Symbol / Material equivalents for each semantic icon.
Size scale
Four sizes, one 4px grid
Every icon size is divisible by 4 — the same base unit as the spacing scale. The 20px default aligns with system-16 text line-height; the 24px size aligns with system-18 and primary actions.
Small
--icon-size-smInline with body text, metadata rows, badge counts
44px wrapper required
Medium
--icon-size-mdNavigation, action buttons, companion to system-16 text
44px wrapper recommended
Large
--icon-size-lgPrimary action buttons, Stories ring, standalone action surface
Self-contained at 44px min button
XL
--icon-size-xlHero moments, empty states, onboarding illustrations
44px minimum if interactive
Style grammar
Filled and outline carry meaning
Instagram icons are binary: filled communicates active/selected; outline communicates resting/unselected. This isn't decoration — it's the system's primary state-change signal for toggleable affordances.
Use when: Selected state, primary/active affordance, brand moments
A filled heart = liked. A filled bookmark = saved. Active tab icon = filled.
Filled icons carry semantic weight — use them only to communicate active or selected state, never decoratively.
Use when: Default/resting state, inactive, secondary affordance
An outline heart = not yet liked. An outline bookmark = unsaved. Inactive tab = outline.
Outline is the default register. Every filled icon should have a matching outline counterpart for the resting state.
Icon vocabulary
Common icon pairs with platform equivalents
Instagram's icon set follows the same semantic grammar as SF Symbols (iOS) and Material Symbols (Android). Each icon below shows outline (resting) and filled (active) at 24px. SF Symbol and Material names are the nearest equivalents for native implementation.
Like / Heart
heartfavorite_borderFeed, Reels, Stories, Comments
Comment
messagechat_bubble_outlineFeed, Reels, Comments action row
Share / Send
paperplanesendFeed actions, DM send button
Save / Bookmark
bookmarkbookmark_borderFeed post actions, Collections
Home / Feed
househomeTab Bar — primary navigation
Profile
personperson_outlineTab Bar, Profile pages
Notifications / Bell
bellnotifications_noneActivity feed, navigation
Camera
cameracamera_altStories creation, profile photo
Platform mapping
SF Symbol & Material Symbol reference
Use these names for native iOS and Android implementations. SF Symbols always come in outline and .fill variants matching this system's filled/outline grammar. Material Symbols use _outline and filled suffixes.
heart/heart.fillfavorite_border/favoritemessage/message.fillchat_bubble_outline/chat_bubblepaperplane/paperplane.fillsendbookmark/bookmark.fillbookmark_border/bookmarkhouse/house.fillhomemagnifyingglasssearchperson/person.fillperson_outline/personbell/bell.fillnotifications_none/notificationspaperplane/paperplane.fillsendplus/plus.app.filladd/add_boxplay.rectangle/play.rectangle.fillplay_circle_outline/play_circlecamera/camera.fillcamera_altgearshape/gearshape.fillsettingsellipsis/ellipsis.circle.fillmore_horizxmark/xmark.circle.fillclose/cancelchevron.leftarrow_backspeaker.slash/speaker.slash.fillvolume_offperson.badge.checkmark/person.badge.checkmark.fillperson_add_disabled/how_to_regperson.2/person.2.fillgroup_outline/groupplay/play.fillplay_arrowPlatform implementation
Native and web usage
Apply the icon grammar consistently across platforms. SF Symbols on iOS natively support filled/outline switching; Material Symbols provide the same via Icons.Filled / Icons.Outlined namespaces.
iOS — SwiftUI + SF Symbols
// Outline (resting) ↔ Filled (active)
Button { isLiked.toggle() } label: {
Image(systemName: isLiked ? "heart.fill" : "heart")
.font(.system(size: 24))
.foregroundStyle(isLiked ? Color.red : Color.primary)
}
.accessibilityLabel(isLiked ? "Unlike" : "Like")
// Use symbolRenderingMode for multi-colour icons
Image(systemName: "person.fill")
.symbolRenderingMode(.hierarchical)
.foregroundStyle(Color.primary)Android — Jetpack Compose
// Outline ↔ Filled via Icons namespace
Icon(
imageVector = if (isLiked)
Icons.Filled.Favorite
else
Icons.Outlined.FavoriteBorder,
contentDescription = if (isLiked) "Unlike" else "Like",
tint = if (isLiked)
MaterialTheme.colorScheme.error
else
LocalContentColor.current,
modifier = Modifier.size(24.dp)
).icon {
display: inline-flex;
align-items: center;
justify-content: center;
color: rgb(var(--ig-primary-icon));
flex-shrink: 0;
}
.icon--sm { width: var(--icon-size-sm); height: var(--icon-size-sm); }
.icon--md { width: var(--icon-size-md); height: var(--icon-size-md); }
.icon--lg { width: var(--icon-size-lg); height: var(--icon-size-lg); }
.icon--xl { width: var(--icon-size-xl); height: var(--icon-size-xl); }
.icon--secondary { color: rgb(var(--ig-secondary-icon)); }
.icon--on-fill { color: rgb(var(--ig-always-white)); }
/* SVG inside inherits currentColor — no fill attr needed */
.icon svg { width: 100%; height: 100%; }Colour
Semantic colour tokens for icons
Icons are coloured with semantic tokens, never hardcoded hex. The primary icon token adapts automatically between light and dark mode.
--ig-primary-iconDefault icon on primary backgroundMost nav and action icons--ig-secondary-iconSubdued icon, metadata, timestampsSecondary action rows, helper icons--ig-always-whiteIcon on dark fill (gradient, photo)Overlays, Stories ring controls, camera UI--ig-errorDestructive action iconDelete, block, report--ig-primary-buttonCTA icon (Send, Follow)Blue send arrow, follow affordanceTouch targets
44px minimum interactive area
Icons smaller than 44px must live inside a 44×44px interactive wrapper. The icon's visual size never changes; only the tap surface expands.
20px icon in 44px wrapper
24px icon self-contained in 44px button
.icon-button {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 44px;
min-height: 44px;
border-radius: var(--radius-pill);
cursor: pointer;
color: rgb(var(--ig-primary-icon));
}
/* The icon's visual size never changes — only the button grows */
.icon-button svg {
width: 20px;
height: 20px;
flex-shrink: 0;
}Typography pairing
Icon weight matches text weight
When pairing an icon with text, choose the icon size whose stroke weight visually matches the text weight. Heavy text (--fw-bold/semibold) pairs with filled or heavier-stroke icons; light body text pairs with outline.
system-1216px16pxmiddlesystem-1418px16pxmiddlesystem-1624px20pxmiddlesystem-1824px20–24pxmiddlesystem-22+26–32px24pxmiddleDo
- Use semantic colour tokens — Colour icons with --ig-primary-icon or --ig-secondary-icon so they adapt to dark mode automatically.
- Pair filled ↔ outline for toggle states — Every icon that represents a binary state (liked/not-liked) must have both a filled and an outline version.
- Wrap small icons in a 44px target — 16px and 20px icons must live inside a 44×44px interactive element — never expose a tiny tap target.
- Use SF Symbols on iOS — Image(systemName:) with the .fill suffix mirrors this system's filled/outline grammar exactly — no custom assets needed for the standard vocabulary.
Don’t
- Don't use fill for decoration — Filled icons signal 'selected' in Instagram's grammar. Using filled icons decoratively confuses the state-change signal.
- Don't use arbitrary sizes — Icon sizes must come from the four-step scale (16 / 20 / 24 / 32). In-between values (18px, 22px) are not part of the system.
- Don't hardcode colour hex — Icons coloured with a hardcoded hex won't adapt to dark mode and lose semantic meaning.
- Don't mix icon libraries on one platform — Pick one source per surface — SF Symbols on iOS, Material on Android, custom SVG on web. Mixing grammar systems breaks visual consistency.