Icons are everywhere in a mobile UI — in the app bar, on buttons, beside list items — and Flutter splits the job in two: Icon draws a glyph, and IconButton makes that glyph tappable, accessible, and properly sized for a finger. Mixing the two up is the single most common icon mistake. This guide covers the Icon widget and Material icon set, sizing and colour, IconButton with its tap target and tooltip, the Material 3 styled variants, and accessibility, with paste-ready code.

The Complete Flutter Guide: Build Android, iOS and Web apps
Go from scratch to building industry-standard apps with Riverpod, Firebase, animations, REST APIs, and more.
Enrol nowEvery snippet below is paste-ready against current stable Flutter. Icons sit beside almost every other widget, so the Material Widgets catalogue and the RichText guide (for inline icons in text) both pair naturally with this one.
We'll work through the Icon widget and the Material icon variants, how size and colour are resolved, the IconButton and its all-important tap target, the Material 3 filled and outlined variants, and how to keep icons accessible.
If watching helps more than reading, the channel wires icons into real toolbars and list items rather than isolated demos.
The Icon widget and Material icons
The Icon widget renders a single glyph from an IconData value. Flutter bundles the full Material icon set in the Icons class, so you rarely add an icon font yourself.
Icon(Icons.favorite, size: 28, color: Colors.red)
Most Material icons ship in style variants — the same shape filled, outlined, rounded, or sharp — accessed by a name suffix: Icons.home, Icons.home_outlined, Icons.home_rounded, Icons.home_sharp. Pick one style and use it consistently; mixing outlined and filled icons in the same bar looks unintentional. For iOS-flavoured apps, CupertinoIcons offers the matching SF-style set, covered in the Cupertino widgets guide.
Size and colour resolution
If you omit size and color, the icon doesn't render as a default grey 24px square at random — it inherits from the ambient IconTheme, which Material widgets like AppBar and ListTile set up for you. That's why an app-bar action icon is automatically the right colour without you specifying it.
// Inherits colour/size from the surrounding IconTheme:
const Icon(Icons.settings)
// Override just for this icon:
const Icon(Icons.settings, size: 20, color: Colors.white70)
Setting an IconTheme over a subtree is the clean way to restyle a group of icons at once, rather than passing size and color to each. Reach for explicit arguments only when one icon needs to differ from its neighbours.
IconButton: making an icon tappable
An Icon ignores taps. To respond to a press, use IconButton, which adds a ripple, a tooltip, and — crucially — a 48-by-48 logical-pixel minimum tap target even when the glyph is small, so it's comfortable to hit with a thumb.
IconButton(
icon: const Icon(Icons.share),
tooltip: 'Share', // shows on long-press and to screen readers
onPressed: () => _share(),
)
The tooltip is not optional polish: it labels the button for accessibility and surfaces a hint on long-press. Set onPressed to null to disable the button — Flutter greys it out and drops the ripple automatically, the same convention every Material button follows.

Build toolbars that feel native
The Complete Flutter Guide covers icons, buttons, and tap targets to Material spec from first principles through to shipped apps.
Enrol nowMaterial 3 IconButton variants
Material 3 adds named constructors that wrap the icon in a styled container, so you no longer hand-roll a coloured circle behind an icon.
IconButton.filled(onPressed: () {}, icon: const Icon(Icons.add)) // solid background
IconButton.filledTonal(onPressed: () {}, icon: const Icon(Icons.edit)) // soft tonal fill
IconButton.outlined(onPressed: () {}, icon: const Icon(Icons.check)) // bordered outline
The plain IconButton(...) constructor remains the standard, container-less button. The variants share the same onPressed and icon arguments, so switching styles is a one-word change. Use a filled variant for the primary action in a row of icons and the standard one for secondary actions.
Sizing the tap target
Sometimes the default 48px target is too generous — a dense row of small icon buttons, for instance. You can tighten it with constraints and padding, but do so deliberately, because shrinking the target below the recommended minimum hurts usability.
IconButton(
icon: const Icon(Icons.close, size: 18),
padding: EdgeInsets.zero,
constraints: const BoxConstraints(minWidth: 32, minHeight: 32),
onPressed: () {},
)
This is the right pattern for a tight chip or a compact toolbar, where 48px would force unwanted spacing. Outside those cases, leave the default alone — the spacing exists for a reason.
Accessibility
A bare decorative Icon conveys nothing to a screen reader. Give a meaningful standalone icon a semanticLabel so it's announced, and rely on the tooltip for icon buttons, which doubles as the accessibility label. An icon that merely decorates adjacent text needs no label — the text already carries the meaning.
const Icon(Icons.warning_amber, semanticLabel: 'Warning')
Common mistakes
- Wrapping an Icon in a GestureDetector for taps. Use
IconButton— you get the ripple, the 48px target, and accessibility for free. - Forgetting the tooltip. It labels the button for screen readers and shows a hint on long-press.
- Mixing icon styles. Stick to one of outlined, filled, rounded, or sharp across a screen.
- Hard-coding colour on every icon. Set an
IconThemeover the subtree instead. - Shrinking the tap target everywhere. Tighten
constraintsonly in genuinely dense UI, not by default.
Frequently asked questions
What is the difference between Icon and IconButton in Flutter?
Icon is a non-interactive glyph; IconButton is a tappable, accessible button with a ripple, a 48px tap target, onPressed, and a tooltip. Use IconButton whenever the icon should react to a tap.
How do I change icon size and colour in Flutter?
Set size and color on the Icon, or restyle a group by wrapping it in an IconTheme. On an IconButton, use iconSize and color.
What are IconButton.filled and IconButton.outlined?
Material 3 variants that give the button a container — solid, tonal, or outlined. The default IconButton has no container.
How do I disable an IconButton in Flutter?
Set onPressed to null; Flutter greys it out and removes the ripple automatically.
Further reads
Keep going with the tutorials that pair with this guide:
- Flutter Development Guide 2026 — the full Flutter hub.
- Flutter Material Widgets: The Complete Catalogue — every Material button and component.
- Flutter RichText and TextSpan — embed icons inline in text with WidgetSpan.
- Flutter Cupertino Widgets — CupertinoIcons for iOS-style UIs.
- Flutter Text and TextStyle — the labels that sit beside your icons.
Sources: Flutter documentation — Icon, Icons, IconData, IconButton, IconTheme, and CupertinoIcons API references, plus the Material 3 icon-button guidance (docs.flutter.dev). Verified against current stable Flutter.