image

19 Jan 2026

9K

35K

Flutter Layout Tips: Mastering Stack and Positioned for Creative UIs

Introduction

Flutter's rich set of layout widgets provides immense flexibility for building beautiful and functional user interfaces. Among the most powerful tools for creating layered, overlapping, or precisely placed elements are the Stack and Positioned widgets. This article delves into how these two widgets work in tandem to unlock a new level of creativity in your Flutter UIs.

Understanding the Stack Widget

The Stack widget in Flutter is designed to layer multiple widgets on top of one another, much like a stack of papers. The first child in the Stack's children list is drawn at the bottom, and subsequent children are drawn on top of the previous ones. By default, all children of a Stack are aligned to the top-left corner.

You can control the default alignment of non-Positioned children using the alignment property of the Stack.

Basic Stack Example


import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Basic Stack Example')),
        body: Center(
          child: Stack(
            alignment: Alignment.center, // Aligns children to the center
            children: [
              Container(
                width: 200,
                height: 200,
                color: Colors.blue,
              ),
              Container(
                width: 150,
                height: 150,
                color: Colors.red,
              ),
              Container(
                width: 100,
                height: 100,
                color: Colors.green,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

In this example, the blue container is at the bottom, followed by red, and then green, all centered within the Stack due to the alignment property.

Leveraging the Positioned Widget

While Stack allows layering, Positioned is the key to precisely placing widgets within that Stack. A Positioned widget must be a direct child of a Stack (or an ancestor that resolves to a Stack, but typically direct). It takes properties like top, bottom, left, right, width, and height to specify its exact location and size relative to the Stack's boundaries.

When a child of a Stack is wrapped in a Positioned widget, its position is no longer affected by the Stack's alignment property. Instead, it relies entirely on the Positioned widget's properties.

Positioned Example


import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Stack and Positioned Example')),
        body: Center(
          child: Container(
            width: 300,
            height: 300,
            color: Colors.grey[200],
            child: Stack(
              children: [
                // Background element
                Positioned.fill(
                  child: Image.network(
                    'https://via.placeholder.com/300x300/CCCCCC/FFFFFF?text=Background',
                    fit: BoxFit.cover,
                  ),
                ),
                // Top-left text
                Positioned(
                  top: 20,
                  left: 20,
                  child: Text(
                    'Top Left',
                    style: TextStyle(color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold),
                  ),
                ),
                // Bottom-right button
                Positioned(
                  bottom: 20,
                  right: 20,
                  child: ElevatedButton(
                    onPressed: () {},
                    child: Text('Action'),
                  ),
                ),
                // Centered icon with custom size
                Positioned(
                  top: 100,
                  left: 100,
                  width: 100,
                  height: 100,
                  child: Icon(
                    Icons.star,
                    color: Colors.yellow,
                    size: 80,
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Notice Positioned.fill which is a convenient constructor to make a child fill the entire Stack, often used for background images or overlays.

Creative UI Use Cases and Tips

The combination of Stack and Positioned opens up a world of possibilities for intricate and visually appealing UIs:

1. Overlapping Profile Pictures and Badges

A common pattern is a user's profile picture with a small status indicator or badge overlapping it.


Stack(
  children: [
    CircleAvatar(
      radius: 40,
      backgroundImage: NetworkImage('https://via.placeholder.com/150'),
    ),
    Positioned(
      bottom: 0,
      right: 0,
      child: Container(
        width: 20,
        height: 20,
        decoration: BoxDecoration(
          color: Colors.green,
          shape: BoxShape.circle,
          border: Border.all(color: Colors.white, width: 2),
        ),
      ),
    ),
  ],
)

2. Text Over Images

Placing text or other widgets directly on top of an image for captions, titles, or interactive elements.


SizedBox(
  width: double.infinity,
  height: 200,
  child: Stack(
    children: [
      Image.network(
        'https://via.placeholder.com/600x200/FF0000/FFFFFF?text=Beautiful+Landscape',
        fit: BoxFit.cover,
        width: double.infinity,
      ),
      Positioned(
        bottom: 10,
        left: 10,
        child: Text(
          'Sunset View',
          style: TextStyle(
            color: Colors.white,
            fontSize: 28,
            fontWeight: FontWeight.bold,
            shadows: [
              Shadow(
                blurRadius: 5.0,
                color: Colors.black.withOpacity(0.5),
                offset: Offset(2.0, 2.0),
              ),
            ],
          ),
        ),
      ),
    ],
  ),
)

3. Custom Overlays and Modals

For custom loading indicators, tooltips, or pop-up messages that need to float above the primary content.


Stack(
  children: [
    // Main content of your screen
    ListView(
      children: List.generate(20, (index) => ListTile(title: Text('Item $index'))),
    ),
    // Overlay (e.g., loading spinner)
    Positioned.fill(
      child: Container(
        color: Colors.black.withOpacity(0.5),
        child: Center(
          child: CircularProgressIndicator(),
        ),
      ),
    ),
  ],
)

4. Floating Action Buttons with Custom Placement

While Scaffold provides a floatingActionButton, Stack and Positioned can be used for more complex custom floating elements, or multiple floating elements.


Stack(
  children: [
    // Your main content
    Container(color: Colors.white),
    Positioned(
      bottom: 20,
      right: 20,
      child: FloatingActionButton(
        onPressed: () {},
        child: Icon(Icons.add),
      ),
    ),
    Positioned(
      bottom: 90, // Position another button above the first
      right: 20,
      child: FloatingActionButton(
        mini: true,
        onPressed: () {},
        child: Icon(Icons.share),
      ),
    ),
  ],
)

Advanced Tips and Considerations

Combine with Align Widget

For children that don't need pixel-perfect positioning but rather alignment to an edge or center, using an Align widget as a child of Stack can be simpler than Positioned. Align respects the Stack's size and places its child according to its alignment property.


Stack(
  children: [
    Container(width: 200, height: 200, color: Colors.blueGrey),
    Align(
      alignment: Alignment.bottomLeft,
      child: Text('Bottom Left', style: TextStyle(color: Colors.white)),
    ),
    Align(
      alignment: Alignment.topRight,
      child: Icon(Icons.info, color: Colors.yellow),
    ),
  ],
)

Responsiveness with MediaQuery

When using Positioned, especially with fixed pixel values, be mindful of different screen sizes. For responsive designs, consider using percentages of screen width/height obtained via MediaQuery.of(context).size.


// Inside a Widget's build method
double screenWidth = MediaQuery.of(context).size.width;
Stack(
  children: [
    // ...
    Positioned(
      left: screenWidth * 0.1, // 10% from left
      top: screenWidth * 0.05, // 5% from top (relative to width for aspect ratio)
      child: Container(
        width: screenWidth * 0.3,
        height: 50,
        color: Colors.purple,
      ),
    ),
  ],
)

Performance

While Stack is generally efficient, avoid overly deep or complex widget trees within its children, especially if many are being constantly rebuilt. For static overlays or a few dynamic elements, performance impact is usually negligible.

Conclusion

The Stack and Positioned widgets are indispensable tools in a Flutter developer's arsenal for crafting sophisticated and visually appealing UIs. By understanding how to layer widgets with Stack and precisely control their placement with Positioned, you can move beyond conventional layouts and bring your most creative design ideas to life. Experiment with these widgets to discover the endless possibilities they offer for unique and engaging user experiences.

Related Articles

May 14, 2026

Building a Multi-Event Countdown Timer Widget with Reminders, Notifications, Repeat, and Custom Labels in Flutter

Building a Multi-Event Countdown Timer Widget with Reminders, Notifications, Repeat, and Custom Labels in Flutter Countdown timers are essential in many applic

May 11, 2026

Unleashing Dynamic UIs: Flutter's Animation Prowess

Unleashing Dynamic UIs: Flutter's Animation Prowess for Slide & Scale Effects Flutter's declarative UI framework, combined with its powerful animation capabilit

May 11, 2026

Building a Product Detail Page Widget in Flutter with Related Items, Review Carousel, Promo Badges, and Quick Buy

Building a Product Detail Page Widget in Flutter with Related Items, Review Carousel, Promo Badges, and Quick Buy A well-designed Product Detail Page (PDP) is