Flutter buttons: ElevatedButton instead of RaisedButton, TextButton, FilledButton
Egor Dolgov · 10.11.2026Flutter 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:
- Which button to choose
- A minimal example
- Main parameters
- Examples: disabled button, icon, size
- Your own style: styleFrom and the theme
- What replaces RaisedButton, FlatButton, OutlineButton and ButtonTheme
- 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”. OnlyFloatingActionButton— the round floating button in a screen corner — stands out more. -
FilledButton.tonal— a middle ground betweenFilledButtonandOutlinedButton: 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, usuallyText. 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
onPressedandonLongPressarenull, the button is disabled: it doesn't react to taps, and Flutter draws it in muted disabled colors. AnIconButtonis disabled byonPressed: nullalone. -
Button with an icon.
FilledButton,ElevatedButton,OutlinedButtonandTextButtonhave an.iconconstructor: the icon goes inicon, the text in the requiredlabel. ForFilledButton.tonalthere isFilledButton.tonalIcon. -
Long press.
onLongPressis called when the button is pressed and held. -
IconButtonvariants. Besides the plain one there areIconButton.filled,IconButton.filledTonalandIconButton.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.
-
fixedSizeinstyleFromsets 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): aSizedBoxwith infinite width stretches the button to the full width its parent allows. -
minimumSizesets the smallest size: by default anElevatedButtonin 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.
-
backgroundColoris the background color,foregroundColorthe color of the text and icon. -
paddingis the inner padding,shapethe shape: here a rectangle with a corner radius of 8. -
On a disabled button
backgroundColorandforegroundColorhave no effect — for it there aredisabledBackgroundColoranddisabledForegroundColor(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 saysnew 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 withFlatButtonandOutlineButtonlook the same. -
The button is pale and can't be tapped.
Its
onPressed(andonLongPress) arenull— for example, you passed a variable that is stillnull. Such a button is disabled. -
The color from
styleFromdoesn't apply. Check that the button isn't disabled: itsonPressedisn'tnull. A disabled button's colors are set bydisabledBackgroundColoranddisabledForegroundColor. -
onPressed: _save()with parentheses. This passes the button the result of the call, not the function. If the function returns nothing (void), the analyzer reportsuse_of_void_result. UseonPressed: _save— without parentheses — oronPressed: () { … }.
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.