Stack & Positioned
Overlapping Widgets Like Layers
Open interactive version (quiz + challenge)Real-world analogy
Stack is like making a collage. You start with a big piece of paper (the base), then layer photos, stickers, and text on top. Each piece overlaps the one below it. Positioned is like pinning a photo to an exact spot on the paper — 20mm from the left edge, 10mm from the top. Align is like saying 'center this sticker' or 'put it in the bottom-right corner'.
What is it?
Stack is a layout widget that layers children on top of each other, with the first child at the bottom and later children on top. Positioned pins a child to exact pixel coordinates within the Stack. Align positions a child using relative alignment values. Together they create overlapping layouts like badges, overlays, banners, and floating elements.
Real-world relevance
In team_mvp_kit, Stack is used for profile headers (image with gradient text overlay), notification badges on icons, loading overlays on screens, floating action buttons with custom positioning, and image cards with price tags. Any time one widget needs to sit on top of another, Stack is the answer.
Key points
- Stack Widget — Stack layers its children on top of each other. The first child is at the bottom, and each subsequent child is painted on top. By default, children are positioned at the top-left corner. Stack is essential for overlays, badges, floating labels, and any UI where widgets need to overlap.
- Positioned Widget — Positioned places a child at exact coordinates within a Stack. You can set top, bottom, left, right, width, and height. It only works as a direct child of Stack. If you set both left and right without width, the child stretches horizontally between those positions.
- Align Widget in Stack — Align positions a child using an Alignment value instead of pixel coordinates. Alignment(-1, -1) is top-left, Alignment(1, 1) is bottom-right, and Alignment(0, 0) is center. Use named constants like Alignment.center, Alignment.bottomRight for convenience. Align works both inside and outside Stack.
- Stack Fit and Alignment — Stack's fit property controls how non-positioned children are sized. StackFit.loose lets children size themselves. StackFit.expand forces children to fill the Stack. The alignment property sets the default alignment for non-positioned children — like setting a default position for all layers.
- Building a Badge — A common Stack pattern is adding a notification badge to an icon. Stack the icon as the base, then Positioned a small red circle with a count at the top-right. This pattern appears in every app with notifications, shopping carts, or message counts.
- Image Overlay Pattern — Stack is commonly used to overlay text, gradients, or buttons on top of images. Place the image as the first child and layer a semi-transparent gradient and text on top. This creates professional-looking hero images, cards, and banners.
- Clip Behavior — By default, Stack clips children that overflow its bounds. Set clipBehavior: Clip.none to allow Positioned children to extend beyond the Stack's edges — useful for badges, decorative elements, or shadows that need to overflow. Be careful though: overflowing content can overlap other widgets.
Code example
import 'package:flutter/material.dart';
class ProfileHeader extends StatelessWidget {
final String name;
final String title;
final String coverUrl;
final String avatarUrl;
const ProfileHeader({
super.key,
required this.name,
required this.title,
required this.coverUrl,
required this.avatarUrl,
});
@override
Widget build(BuildContext context) {
return Stack(
clipBehavior: Clip.none,
children: [
// Layer 1: Cover image
Image.network(
coverUrl,
height: 200,
width: double.infinity,
fit: BoxFit.cover,
),
// Layer 2: Gradient overlay
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
height: 80,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [
Colors.black.withOpacity(0.7),
Colors.transparent,
],
),
),
),
),
// Layer 3: Name and title on the gradient
Positioned(
bottom: 16,
left: 16,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
name,
style: const TextStyle(
color: Colors.white,
fontSize: 22,
fontWeight: FontWeight.bold,
),
),
Text(
title,
style: TextStyle(
color: Colors.white.withOpacity(0.8),
fontSize: 14,
),
),
],
),
),
// Layer 4: Avatar overlapping the bottom edge
Positioned(
bottom: -40,
right: 16,
child: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 3),
),
child: CircleAvatar(
radius: 40,
backgroundImage: NetworkImage(avatarUrl),
),
),
),
],
);
}
}Line-by-line walkthrough
- 1. Import the Material package
- 2.
- 3. Define ProfileHeader as a StatelessWidget
- 4. Declare required fields for name, title, and image URLs
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13. Build method returns the widget tree
- 14.
- 15. Stack is the main layout that layers everything
- 16. clipBehavior: Clip.none allows the avatar to overflow below
- 17.
- 18. The first layer: cover image at the bottom
- 19. Load the cover image from a URL
- 20. Fixed height of 200px, full width
- 21. Scale and crop to fill the area
- 22.
- 23. The second layer: gradient overlay
- 24. Positioned at the bottom, stretching left to right
- 25.
- 26. Container with 80px height for the gradient
- 27. LinearGradient from black at bottom to transparent at top
- 28. Creates a fade effect for text readability
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35. The third layer: name and title text
- 36. Positioned 16px from bottom and 16px from left
- 37. Column to stack name above title
- 38. Left-align the text
- 39.
- 40. Name in white, large, bold text
- 41.
- 42.
- 43.
- 44.
- 45. Title in slightly transparent white, smaller
- 46.
- 47.
- 48.
- 49.
- 50.
- 51. The fourth layer: avatar overlapping the bottom edge
- 52. bottom: -40 pushes it 40px below the Stack's bottom edge
- 53. Right-aligned at 16px from the right
- 54.
- 55. Container adds a white circular border around the avatar
- 56. CircleAvatar of 40px radius
- 57. Load the avatar image from URL
- 58.
- 59.
- 60.
- 61.
Spot the bug
Stack(
children: [
Image.network('https://example.com/bg.jpg'),
Positioned(
bottom: -20,
child: CircleAvatar(radius: 30),
),
],
)Need a hint?
The avatar should overflow below the Stack, but it is being clipped. What property controls this?
Show answer
By default Stack clips overflowing children. The avatar at bottom: -20 is clipped and invisible. Fix: add clipBehavior: Clip.none to the Stack so the avatar can extend below the Stack's bounds.
Explain like I'm 5
Imagine you are making a poster for your room. First you put up a big picture (the background). Then you tape a sticker on top (second layer). Then you write your name with a marker on top of everything (third layer). That is Stack! Positioned is like using a ruler to tape the sticker exactly 2 inches from the top and 3 inches from the left. And Align is like saying 'put the sticker right in the middle of the poster' without measuring.
Fun fact
Stack is inspired by the concept of z-index in CSS. In web development you use position: absolute and z-index to layer elements. Flutter's Stack does the same thing but in a more structured way — the order of children in the list determines the z-order, with later children on top!
Hands-on challenge
Build a profile header card using Stack: a cover image as the background, a dark gradient overlay at the bottom for text readability, the user's name and bio positioned at the bottom-left over the gradient, and a CircleAvatar that overlaps the bottom edge of the cover image (use clipBehavior: Clip.none and a negative bottom position). Add a white border around the avatar.
More resources
- Stack Class (Flutter API)
- Positioned Class (Flutter API)
- Layouts in Flutter (Flutter Official)