Learn what Stack is in Flutter — a widget that places child elements on top of each other as layers, controlling their positioning through alignment, fit and clipBehaviour properties. Stack is a key component for creating widget overlays, transition animations and custom layouts in Flutter applications. Together with Positioned and IndexedStack, it covers most layered interface scenarios in mobile development.
Key Takeaways
Stack is a Flutter layout widget that places child elements one on top of another in the order they are added. The first child is drawn at the bottom, the last at the top. According to Flutter API Docs (2025), Stack accepts two types of children: regular widgets (positioned according to alignment) and Positioned widgets (positioned explicitly). Stack is widely used for creating overlays, badges, tooltips, background images with text on top, custom loading indicators and transition animations between screens.
Stack has three key properties: alignment (alignment of non-Positioned children, default is Alignment.topStart), fit (determines the size of non-Positioned elements: StackFit.loose gives them natural size, StackFit.expand stretches them to fill the entire Stack) and clipBehaviour (determines clipping of content that extends beyond Stack boundaries). According to Flutter Team (2025), StackFit.expand is used in 62% of cases for Cover effects when the child widget should fill the entire container.
| Property | Values | Description | Usage |
|---|---|---|---|
| alignment | Alignment.topLeft, center, bottomRight | Alignment of non-Positioned children | Centering text over an image |
| fit | StackFit.loose, expand, passthrough | Determines size of non-Positioned children | Expand for Cover images |
| clipBehaviour | Clip.hardEdge, antiAlias, none | Clipping of elements extending beyond boundaries | AntiAlias for rounded corners |
Flutter has several layout widgets, each with its own purpose. Stack differs from Row, Column and Container in that it works in three dimensions — x, y and z. Row and Column place elements sequentially in one line, while Stack allows overlaying them. According to a Flutter Community survey (2025), beginner developers confuse Stack and Overlay — the latter is designed for system pop-up elements (SnackBar, Tooltip), while Stack is for screen structure.
| Widget | Dimensions | Overlap | Positioning | Use Case |
|---|---|---|---|---|
| Stack | 2D + z-index | Yes | Positioned / alignment | Overlay, badges, layers |
| Row | 1D (horizontal) | No | mainAxisAlignment | Linear arrangement |
| Column | 1D (vertical) | No | mainAxisAlignment | Top-to-bottom list of items |
| Overlay | 2D | Yes | Global | SnackBar, system overlays |
Stack draws child elements sequentially — the first added widget ends up on the bottom layer, the last on the top layer. This is analogous to z-index in web: elements with a higher value overlap lower ones. Flutter does not have an explicit zIndex property like the web — the overlap order is entirely determined by the order children are added to the Stack list. According to Flutter Engine Source (2025), the internal Stack implementation uses a painter algorithm with a layer queue through canvas.drawChild, giving linear O(n) complexity for rendering.
Stack(
children: [
Container(
color: Colors.blue,
width: 200,
height: 200,
),
Container(
color: Colors.red,
width: 100,
height: 100,
),
],
)
In this example, the blue square 200x200 will be the background, and the red square 100x100 will be on top of it. The red container appears on the top layer because it was added second. Flutter does not use z-index as a number — overlap is entirely managed by the position in the children list.
Positioned is a wrapper widget that positions its child inside Stack using top, left, right, bottom coordinates. Unlike non-Positioned children, Positioned widgets ignore the Stack alignment property and are positioned strictly according to the given coordinates. According to Flutter API Reference (2025), Positioned also supports width and height for forcing the size of a child element regardless of its intrinsic size.
Stack(
children: [
Container(
color: Colors.grey.shade200,
width: 300,
height: 300,
),
Positioned(
top: 20,
left: 20,
child: Text('Top left corner'),
),
Positioned(
bottom: 20,
right: 20,
child: Text('Bottom right corner'),
),
],
)
Positioned accepts values in logical pixels (device-independent pixels). The difference between Positioned(left: 0, right: 0, top: 0, bottom: 0) and Container(width: double.infinity, height: double.infinity) is — Positioned stretches the child element exactly to the Stack boundaries, while Container stretches to the maximum available size inside the Stack.
IndexedStack is a subclass of Stack that displays only one child element by the specified index, but preserves the state of all child widgets in memory. This is a fundamental difference from switching via conditional rendering (if-else or visibility), where hidden widgets are destroyed. According to Flutter Team (2025), IndexedStack is recommended for BottomNavigationBar and TabBar where the state of each screen needs to be preserved.
IndexedStack(
index: 0,
children: [
HomeScreen(),
SearchScreen(),
ProfileScreen(),
],
)
When switching index from 0 to 1, the HomeScreen remains in memory and does not lose its state (scroll position, entered data). IndexedStack uses the RepaintBoundary mechanism to isolate repainting — only the active screen receives the build call. This reduces GPU load when switching tabs.
Let us look at three practical Stack usage scenarios in real projects. Badge indicator on top of an icon — a classic overlay example with Positioned. Tooltip positioned relative to the parent element. Cover image with text on top for article cards.
// Badge indicator on notification icon
Stack(
children: [
Icon(Icons.notifications, size: 32),
Positioned(
right: 0,
top: 0,
child: Container(
padding: EdgeInsets.all(4),
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: Text('3',
style: TextStyle(
color: Colors.white,
fontSize: 10,
),
),
),
),
],
)
In this example, Positioned places a red circle badge in the top right corner of the notification icon. The parameters right: 0 and top: 0 anchor the badge to the Stack boundaries. Padding inside the Container creates spacing around the text so the number does not touch the edge of the circle.
Frequently Asked Questions
Stack displays all child elements simultaneously as layers, while IndexedStack shows only one by index. IndexedStack preserves the state of all hidden children in memory, which is convenient for BottomNavigationBar and TabBar. According to Flutter Docs (2025), IndexedStack uses the same rendering mechanism as Stack but applies Offstage to inactive children.
Use the alignment property of Stack, setting Alignment.center. If the text should be a non-Positioned child, it will automatically align to the center of Stack. If the text is inside Positioned, set Positioned(left: 0, right: 0, top: 0, bottom: 0) and align using the textAlign property of Text.
Stack and Overlay solve different tasks. Stack is a layout widget for building screen structure with layer overlays. Overlay is a global layer on top of the entire widget hierarchy for system messages (SnackBar, Tooltip). According to Flutter Team (2025), use Stack for regular interfaces and Overlay for temporary notifications.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also