The Flutter Stack widget is a layout widget that positions its children relative to the edges of its box. Unlike other layout widgets in Flutter such as Column or Row that arrange elements linearly, the Flutter Stack allows widgets to overlap, making it perfect for creating complex UIs with layered elements.
The Flutter Stack widget follows a simple principle: it positions children relative to its edges (top, right, bottom, left) or positions them according to coordinates provided by the Positioned widget.
Let's explore the essential properties that make the Flutter Stack widget a powerful tool in your Flutter development arsenal:
alignment: Alignment.center
The alignment
property determines how the non-positioned children are aligned within the Flutter Stack. By default, it's set to AlignmentDirectional.topStart
, placing children at the top-left corner in left-to-right languages.
Possible values include:
Alignment.topLeft
Alignment.center
Alignment.bottomRight
fit: StackFit.loose
The fit
property controls how non-positioned children are sized within the Flutter Stack. The default value is StackFit.loose
, allowing children to determine their own size.
Available options include:
StackFit.loose
: Children size themselves freelyStackFit.expand
: Children expand to fill the stack's boundsStackFit.passthrough
: Stack passes its constraints to childrenclipBehavior: Clip.hardEdge
This property determines how the content of the Flutter Stack widget is clipped when it overflows its boundaries. The default value is Clip.hardEdge
, which clips the content at the stack's edges.
Options include:
Clip.none
: No clippingClip.hardEdge
: Clips at the edge without anti-aliasingClip.antiAlias
: Clips with anti-aliasingClip.antiAliasWithSaveLayer
: Clips with anti-aliasing and saves to an intermediate layertextDirection: TextDirection.ltr
The textDirection
property influences the interpretation of AlignmentDirectional
values in the Flutter Stack widget. It's particularly important for right-to-left languages.
Now that we understand the Flutter Stack widget and its properties, let's explore practical examples to see it in action.
Stack(
alignment: Alignment.center,
children: <Widget>[
Container(
width: 300,
height: 300,
color: Colors.blue,
),
Container(
width: 200,
height: 200,
color: Colors.red,
),
Container(
width: 100,
height: 100,
color: Colors.green,
),
],
)
In this example, the Flutter Stack widget positions three differently sized containers on top of each other, centered within the stack's boundaries. The result is three concentric colored squares.
Stack(
children: <Widget>[
Container(
width: 300,
height: 300,
color: Colors.grey,
),
Positioned(
top: 20,
right: 20,
child: Container(
width: 100,
height: 100,
color: Colors.red,
),
),
Positioned(
bottom: 20,
left: 20,
child: Container(
width: 100,
height: 100,
color: Colors.green,
),
),
Positioned(
bottom: 20,
right: 20,
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
],
)
This example demonstrates how to use the Flutter Stack widget with Positioned widgets to place elements at specific coordinates within the stack. The result is a grey background with three colored squares positioned at different corners.
Stack(
clipBehavior: Clip.none,
children: <Widget>[
Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 5,
blurRadius: 7,
offset: Offset(0, 3),
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(height: 50),
Text('Flutter Stack Widget Demo'),
SizedBox(height: 20),
Text('This is a custom card created using Stack'),
],
),
),
Positioned(
top: -50,
left: 0,
right: 0,
child: Center(
child: CircleAvatar(
radius: 50,
backgroundColor: Colors.blue,
child: Icon(
Icons.star,
size: 50,
color: Colors.white,
),
),
),
),
],
)
This example showcases how to create a custom card with an overlapping avatar using the Flutter Stack widget. The CircleAvatar is positioned to overlap the top of the card, creating an engaging UI element.
Stack(
children: <Widget>[
Icon(
Icons.notifications,
size: 40,
),
Positioned(
top: 0,
right: 0,
child: Container(
padding: EdgeInsets.all(2),
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(10),
),
constraints: BoxConstraints(
minWidth: 16,
minHeight: 16,
),
child: Text(
'3',
style: TextStyle(
color: Colors.white,
fontSize: 10,
),
textAlign: TextAlign.center,
),
),
),
],
)
This example demonstrates how to use the Flutter Stack widget to create a notification badge. The badge is positioned at the top-right corner of the notification icon, creating a common UI pattern for indicating unread notifications.
Stack(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width,
height: 200,
color: Colors.blue,
),
Positioned(
bottom: 20,
left: 20,
child: Text(
'Flutter Stack Example',
style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
),
],
)
This technique demonstrates how to create responsive UIs using MediaQuery with a Flutter Stack widget, ensuring elements scale appropriately across different device sizes.
Stack(
children: <Widget>[
// Background layer
AnimatedPositioned(
duration: Duration(milliseconds: 500),
top: -scrollPosition * 0.2,
child: Image.asset(
'assets/background.jpg',
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * 0.5,
fit: BoxFit.cover,
),
),
// Foreground content
AnimatedPositioned(
duration: Duration(milliseconds: 500),
top: 100 - scrollPosition * 0.1,
child: Container(
width: MediaQuery.of(context).size.width,
child: Text(
'Flutter Stack Parallax',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 32,
fontWeight: FontWeight.bold,
),
),
),
),
],
)
This advanced technique shows how to create a parallax scrolling effect using the Flutter Stack widget with AnimatedPositioned, creating depth and visual interest in your UI.