Migration to Flutter Guide
Discover our battle-tested 21-step framework for a smooth and successful migration to Flutter!
Home
Glossary

IconButton in Flutter

What is an IconButton in Flutter?

IconButton is a Flutter Material widget that renders a single icon as a tappable control, typically used for actions like favorite, share, or close where a text label would add unnecessary clutter.

Material 3 provides .filled, .filledTonal, and .outlined variants, as well as support for selected states through isSelected. Unlike TextButton.icon or FilledButton.icon, which combine an icon with a visible text label, IconButton is designed for icon-only actions.

Key facts at a glance

  • IconButton is part of Flutter's Material library and requires no external package.
  • Material 3 provides three built-in styles: IconButton.filled, IconButton.filledTonal, and IconButton.outlined.
  • Setting isSelected makes the button represent a selected state; when selectedIcon is provided, Flutter displays it while the button is selected. The app is responsible for changing the isSelected value.
  • Flutter has no dedicated CupertinoIconButton class – the iOS-style pattern is CupertinoButton with an Icon (or another widget) as its child.
  • Setting onPressed to null disables the button. For an icon-only button, providing a tooltip is recommended to give it an accessible label.

How do I add an IconButton in Flutter?

A plain IconButton needs only an icon and an onPressed callback, but a tooltip is what makes it accessible.

import 'package:flutter/material.dart';
class FavoriteButton extends StatelessWidget {
  const FavoriteButton({super.key, required this.onToggle});
  final VoidCallback onToggle;
  @override
  Widget build(BuildContext context) {
    return IconButton(
      icon: const Icon(Icons.favorite_border),
      tooltip: 'Add to favorites',
      onPressed: onToggle,
    );
  }
}

Without a tooltip, an icon-only button may not have a meaningful accessible label for screen reader users. Providing a descriptive tooltip helps communicate the button's purpose.

How do I create a toggle or filled IconButton in Flutter?

With isSelected, an IconButton can reflect whether an action is currently active. If you provide selectedIcon, Flutter uses it whenever the button is in the selected state.

import 'package:flutter/material.dart';

class LikeToggle extends StatefulWidget {
  const LikeToggle({super.key});

  @override
  State<LikeToggle> createState() => _LikeToggleState();
}

class _LikeToggleState extends State<LikeToggle> {
  bool _liked = false;

  @override
  Widget build(BuildContext context) {
    return IconButton.filledTonal(
      isSelected: _liked,
      icon: const Icon(Icons.favorite_border),
      selectedIcon: const Icon(Icons.favorite),
      tooltip: _liked ? 'Unlike' : 'Like',
      onPressed: () => setState(() => liked = !liked),
    );
  }
}

IconButton.filledTonal gives the toggle a visible background so its selected state reads clearly, which a plain IconButton can't show on its own.

When should I use IconButton – and when not?

Use it when

  • The action is universally recognizable from its icon alone (close, back, search, favorite).
  • You need a compact control in an AppBar, list tile, or toolbar.
  • The control represents a selected or toggle state – use isSelected rather than maintaining separate widgets for each state.

Avoid it when

  • The action's meaning isn't obvious from an icon alone – pair it with a label using TextButton.icon, OutlinedButton.icon, or FilledButton.icon instead.
  • You're building an iOS-focused interface and need a native Cupertino look – prefer CupertinoButton with an icon as its child.
  • The action needs a prominent text label to communicate its purpose or priority – a FilledButton or another labeled button may be a better choice.

IconButton vs. CupertinoButton with an icon

IconButton (Material)CupertinoButton (icon child)
Styles
.filled, .filledTonal, .outlined.filled, .tinted
Toggle support
Built in via isSelected and selectedIconNot built in – manage state manually
Layout / sizing
Designed as a compact icon controlGeneral-purpose button whose padding and sizing can be customized
Accessibility
Use tooltip to provide a descriptive label for an icon-only buttonUse an appropriate semantic label or surrounding text as needed
Best for
Material or cross-platform appsiOS-focused interfaces that use Cupertino styling and behavior

Verdict: use IconButton in Material or adaptive apps; use CupertinoButton with an icon child when building an interface specifically for iOS.

Best practices

  1. Provide a descriptive tooltip for icon-only controls so their purpose is clear to screen reader users.
  2. Use isSelected and selectedIcon to represent a selected state instead of maintaining separate IconButton widgets for each state.
  3. Reach for .filled or .filledTonal when the icon needs stronger visual emphasis than a plain IconButton.
  4. Customize the icon size through IconButton.iconSize rather than Icon.size, so the button can size its splash area appropriately.
  5. Keep the button's default constraints when possible to preserve a comfortable touch target; customize them only when your layout requires a different size.

Common mistakes

  • Skipping tooltip. An icon-only button may lack a meaningful accessible label, and sighted users also lose the hover hint on desktop and web.
  • Manually swapping icons or maintaining separate IconButton widgets for each state. Use isSelected and selectedIcon to represent the selected state instead; the app still controls the isSelected value.
  • Changing Icon.size directly or overriding the button's constraints just to resize an IconButton. Use iconSize on IconButton instead: it lets the button size its splash area appropriately for the icon. Setting a larger size through Icon.size instead may leave the button sized for its default 24-pixel icon, causing the larger icon to be clipped.
  • Using IconButton when the action's meaning is not clear from the icon alone. If users need a text label to understand the action, use TextButton.icon, OutlinedButton.icon, or FilledButton.icon instead.
  • "Disabling" an IconButton by setting its color to grey instead of passing null to onPressed. The button stays tappable and announces as enabled; only onPressed: null truly disables it.

Learn more

RTL in Flutter by LeanCode

Right to Left (RTL) in Flutter App - Developer's Guide

Find the most important things to keep in mind when introducing RTL design in your Flutter mobile app and how you can use Flutter to support various text directions with little effort. Follow the guide on RTL prepared by Flutter Developer.

Is Flutter good for app development?

Flutter Pros and Cons: Why Choose Flutter in 2025?

Flutter is loved by many for its simple and fast development of high-quality cross-platform apps. Let’s take a closer look if Flutter is a suitable solution in every case, i.e., when developing mobile, web, and desktop applications.