Lesson 25 of 51 intermediate

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

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. 1. Import the Material package
  2. 2.
  3. 3. Define ProfileHeader as a StatelessWidget
  4. 4. Declare required fields for name, title, and image URLs
  5. 5.
  6. 6.
  7. 7.
  8. 8.
  9. 9.
  10. 10.
  11. 11.
  12. 12.
  13. 13. Build method returns the widget tree
  14. 14.
  15. 15. Stack is the main layout that layers everything
  16. 16. clipBehavior: Clip.none allows the avatar to overflow below
  17. 17.
  18. 18. The first layer: cover image at the bottom
  19. 19. Load the cover image from a URL
  20. 20. Fixed height of 200px, full width
  21. 21. Scale and crop to fill the area
  22. 22.
  23. 23. The second layer: gradient overlay
  24. 24. Positioned at the bottom, stretching left to right
  25. 25.
  26. 26. Container with 80px height for the gradient
  27. 27. LinearGradient from black at bottom to transparent at top
  28. 28. Creates a fade effect for text readability
  29. 29.
  30. 30.
  31. 31.
  32. 32.
  33. 33.
  34. 34.
  35. 35. The third layer: name and title text
  36. 36. Positioned 16px from bottom and 16px from left
  37. 37. Column to stack name above title
  38. 38. Left-align the text
  39. 39.
  40. 40. Name in white, large, bold text
  41. 41.
  42. 42.
  43. 43.
  44. 44.
  45. 45. Title in slightly transparent white, smaller
  46. 46.
  47. 47.
  48. 48.
  49. 49.
  50. 50.
  51. 51. The fourth layer: avatar overlapping the bottom edge
  52. 52. bottom: -40 pushes it 40px below the Stack's bottom edge
  53. 53. Right-aligned at 16px from the right
  54. 54.
  55. 55. Container adds a white circular border around the avatar
  56. 56. CircleAvatar of 40px radius
  57. 57. Load the avatar image from URL
  58. 58.
  59. 59.
  60. 60.
  61. 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

Open interactive version (quiz + challenge) ← Back to course: Flutter & Dart