Flutter buttons: ElevatedButton instead of RaisedButton, TextButton, FilledButton

Egor Dolgov · 10.11.2026
Chrome
localhost
Buttons
FilledButton
ElevatedButton
OutlinedButton
TextButton
onPressed: () { … }
Show me step by step
Subtitles
Flutter has five kinds of Material Design buttons. They differ in how prominent they are, and all of them take the tap action the same way: a function in onPressed.

The Material Design buttons in Flutter are FilledButton , ElevatedButton , OutlinedButton , TextButton and IconButton . They differ in how prominent they are on screen, and all of them take the tap action the same way — as a function in onPressed . All examples use Material 3: this version of the design is on by default in Flutter.

If you are looking for RaisedButton or FlatButton : they were replaced — RaisedButton → ElevatedButton , FlatButton → TextButton , OutlineButton → OutlinedButton . A before/after example, the versions and what replaces ButtonTheme are in section 6.

Contents:

  1. Which button to choose
  2. A minimal example
  3. Main parameters
  4. Examples: disabled button, icon, size
  5. Your own style: styleFrom and the theme
  6. What replaces RaisedButton, FlatButton, OutlineButton and ButtonTheme
  7. Common mistakes

1. Which button to choose

Per the Flutter documentation:

  • FilledButton — the most prominent of these buttons, for the main action that completes a step: “Save”, “Confirm”. Only FloatingActionButton — the round floating button in a screen corner — stands out more.
  • FilledButton.tonal — a middle ground between FilledButton and OutlinedButton : filled with a secondary, calmer theme color — more noticeable than an outlined button, quieter than a filled one. For example, “Next”.
  • ElevatedButton — a raised button with a shadow. Use it to add depth to a mostly flat layout, for example in a long list. Don't put it on raised elements: dialogs and cards.
  • OutlinedButton — a button with an outline: for an important action, but not the main one.
  • TextButton — a button without an outline: on toolbars, in dialogs, next to text. Don't put it where it blends in with the content, for example in the middle of a list.
  • IconButton — an icon button, often in the app bar ( AppBar.actions ).

2. A minimal example

The five kinds of buttons and the FilledButton.tonal variant on one screen:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Buttons')),
        body: const Center(child: ButtonsDemo()),
      ),
    );
  }
}

class ButtonsDemo extends StatelessWidget {
  const ButtonsDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      spacing: 12,
      children: [
        FilledButton(onPressed: () {}, child: const Text('FilledButton')),
        FilledButton.tonal(
          onPressed: () {},
          child: const Text('FilledButton.tonal'),
        ),
        ElevatedButton(onPressed: () {}, child: const Text('ElevatedButton')),
        OutlinedButton(onPressed: () {}, child: const Text('OutlinedButton')),
        TextButton(onPressed: () {}, child: const Text('TextButton')),
        IconButton(onPressed: () {}, icon: const Icon(Icons.favorite_border)),
      ],
    );
  }
}

On screen: a column of six centered buttons, 12 pixels apart ( spacing: 12 ).

3. Main parameters

Common parameters of FilledButton , ElevatedButton , OutlinedButton and TextButton :

  • onPressed ( VoidCallback? ) — the function the button calls on tap.
  • onLongPress ( VoidCallback? ) — the function for a long press.
  • child ( Widget? ) — what's on the button, usually Text . Required.
  • style ( ButtonStyle? ) — how the button looks: colors, padding, size, shape (section 5).

VoidCallback is a function with no parameters that returns nothing, for example () { … } . A ? after a type means you can pass null instead of a value. IconButton takes a required icon instead of child .

4. Examples: disabled button, icon, size

How to disable a button, add an icon and a long press

import 'package:flutter/material.dart';

void main() {
  runApp(
    const MaterialApp(
      home: Scaffold(body: Center(child: Variants())),
    ),
  );
}

class Variants extends StatelessWidget {
  const Variants({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      spacing: 12,
      children: [
        // A disabled button: onPressed and onLongPress are null.
        const ElevatedButton(onPressed: null, child: Text('Disabled')),
        // A button with an icon.
        FilledButton.icon(
          onPressed: () {},
          icon: const Icon(Icons.send),
          label: const Text('Send'),
        ),
        // A long press.
        TextButton(
          onPressed: () {},
          onLongPress: () {},
          child: const Text('Press and hold'),
        ),
        // IconButton variants.
        Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            IconButton(onPressed: () {}, icon: const Icon(Icons.add)),
            IconButton.filled(onPressed: () {}, icon: const Icon(Icons.add)),
            IconButton.filledTonal(
              onPressed: () {},
              icon: const Icon(Icons.add),
            ),
            IconButton.outlined(onPressed: () {}, icon: const Icon(Icons.add)),
          ],
        ),
      ],
    );
  }
}

On screen: a column with a pale disabled button, a button with an icon, a text button and a row of four icon buttons.

  • Disabled button. If onPressed and onLongPress are null , the button is disabled: it doesn't react to taps, and Flutter draws it in muted disabled colors. An IconButton is disabled by onPressed: null alone.
  • Button with an icon. FilledButton , ElevatedButton , OutlinedButton and TextButton have an .icon constructor: the icon goes in icon , the text in the required label . For FilledButton.tonal there is FilledButton.tonalIcon .
  • Long press. onLongPress is called when the button is pressed and held.
  • IconButton variants. Besides the plain one there are IconButton.filled , IconButton.filledTonal and IconButton.outlined — filled with the primary color, filled with a calmer color, and outlined.

How to set a button's size and make it full width

import 'package:flutter/material.dart';

void main() {
  runApp(
    const MaterialApp(
      home: Scaffold(body: Center(child: Sizes())),
    ),
  );
}

class Sizes extends StatelessWidget {
  const Sizes({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      spacing: 12,
      children: [
        // An exact size: 200 × 60.
        ElevatedButton(
          onPressed: () {},
          style: ElevatedButton.styleFrom(fixedSize: const Size(200, 60)),
          child: const Text('200 × 60'),
        ),
        // Full width: a SizedBox with infinite width.
        SizedBox(
          width: double.infinity,
          child: FilledButton(
            onPressed: () {},
            child: const Text('Full width'),
          ),
        ),
      ],
    );
  }
}

On screen: a 200 × 60 button and, under it, a full-width button.

  • fixedSize in styleFrom sets the button's size: here 200 × 60. Width only — Size.fromWidth(320) , height only — Size.fromHeight(100) .
  • A full-width button goes inside SizedBox(width: double.infinity) : a SizedBox with infinite width stretches the button to the full width its parent allows.
  • minimumSize sets the smallest size: by default an ElevatedButton in Material 3 is 64 × 40.

The size used to be set with ButtonTheme(minWidth:, height:) ; the new buttons use fixedSize and minimumSize for that.

5. Your own style: styleFrom and the theme

A button's look is a ButtonStyle object in the style parameter. The easiest way to build it is the styleFrom method — from colors, padding and sizes. Every button has this method:

import 'package:flutter/material.dart';

void main() {
  runApp(
    const MaterialApp(
      home: Scaffold(body: Center(child: StyledButton())),
    ),
  );
}

class StyledButton extends StatelessWidget {
  const StyledButton({super.key});

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () {},
      style: ElevatedButton.styleFrom(
        backgroundColor: Colors.deepPurple,
        foregroundColor: Colors.white,
        padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 16),
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
      ),
      child: const Text('Custom button'),
    );
  }
}

On screen: a purple button with white text and corners rounded by 8. By default its ends are fully rounded — that's what shape changes.

  • backgroundColor is the background color, foregroundColor the color of the text and icon.
  • padding is the inner padding, shape the shape: here a rectangle with a corner radius of 8.
  • On a disabled button backgroundColor and foregroundColor have no effect — for it there are disabledBackgroundColor and disabledForegroundColor (example in section 6).

Other styleFrom parameters — minimumSize , fixedSize , elevation , side (the outline), textStyle — are described in the ElevatedButton.styleFrom reference .

To avoid repeating style on every button, set it in the app theme — the ThemeData object in the theme parameter of MaterialApp . Each kind of button has its own field in ThemeData : elevatedButtonTheme , filledButtonTheme , outlinedButtonTheme , textButtonTheme , iconButtonTheme . The field takes a …ThemeData object, for example ElevatedButtonThemeData :

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      theme: ThemeData(
        elevatedButtonTheme: ElevatedButtonThemeData(
          style: ElevatedButton.styleFrom(minimumSize: const Size(200, 48)),
        ),
      ),
      home: Scaffold(
        body: Center(
          child: ElevatedButton(
            onPressed: () {},
            child: const Text('Size from the theme'),
          ),
        ),
      ),
    ),
  );
}

Now every ElevatedButton in the app has a minimum size of 200 × 48.

6. What replaces RaisedButton, FlatButton, OutlineButton and ButtonTheme

The replacements come from the migration guide :

  • RaisedButton → ElevatedButton ; theme: elevatedButtonTheme: ElevatedButtonThemeData(…)
  • FlatButton → TextButton ; theme: textButtonTheme: TextButtonThemeData(…)
  • OutlineButton → OutlinedButton ; theme: outlinedButtonTheme: OutlinedButtonThemeData(…)

The color parameters of the old buttons ( color , textColor ) moved to styleFrom :

import 'package:flutter/material.dart';

void main() {
  runApp(
    const MaterialApp(
      home: Scaffold(body: Center(child: SaveButton(enabled: true))),
    ),
  );
}

class SaveButton extends StatelessWidget {
  const SaveButton({super.key, required this.enabled});

  final bool enabled;

  @override
  Widget build(BuildContext context) {
    // Before: RaisedButton(color: Colors.blue, textColor: Colors.white, …)
    return ElevatedButton(
      onPressed: enabled ? () {} : null,
      style: ElevatedButton.styleFrom(
        backgroundColor: Colors.blue,
        foregroundColor: Colors.white,
        disabledBackgroundColor: Colors.blueGrey,
        disabledForegroundColor: Colors.white70,
      ),
      child: const Text('Save'),
    );
  }
}

The old buttons were deprecated in Flutter 2.0. OutlineButton was removed by version 3.0, RaisedButton and FlatButton by 3.3. That's why code from old articles doesn't build on modern Flutter.

ButtonTheme isn't used by the new buttons: their look is set by a single ButtonStyle object instead of many separate parameters — through style and styleFrom (section 5), and for all buttons at once through the theme.

7. Common mistakes

  • The method 'RaisedButton' isn't defined for the type '…' . If the code says new RaisedButton(…) , the text is different — The name 'RaisedButton' isn't a class , and if the button is created outside a class — The function 'RaisedButton' isn't defined . The code was written for an old version of Flutter — replace the button using the table in section 6. Errors with FlatButton and OutlineButton look the same.
  • The button is pale and can't be tapped. Its onPressed (and onLongPress ) are null — for example, you passed a variable that is still null . Such a button is disabled.
  • The color from styleFrom doesn't apply. Check that the button isn't disabled: its onPressed isn't null . A disabled button's colors are set by disabledBackgroundColor and disabledForegroundColor .
  • onPressed: _save() with parentheses. This passes the button the result of the call, not the function. If the function returns nothing ( void ), the analyzer reports use_of_void_result . Use onPressed: _save — without parentheses — or onPressed: () { … } .

See also: Lesson 1 — the first FilledButton in an app; reference for ButtonStyle , FilledButton , IconButton .

Send questions and suggestions about this article to contact@flutter.su.