Flutter Expanded widget

Flutter: Expanded Widget

When building user interfaces in Flutter, it’s common to need multiple widgets to share space equally or in a flexible way. That’s where the Expanded widget shines.

In this article, we’ll explore what the Expanded widget does, how to use it, and how it behaves inside a Column or Row. We’ll also cover the flex property, best practices, and common mistakes to avoid.

What Is the Expanded Widget?

The Expanded widget lets a child of a Row, Column, or Flex widget fill up the remaining available space.

You can think of Expanded like this: “Let this widget grow to fill up as much space as it can, based on the available room and how many other Expanded widgets are around”.

Basic Example

Let’s say we have a row with two containers. One has a fixed width, and the other should take up all the remaining space. Here’s how to achieve that using Expanded:

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Expanded Widget',
      home: Scaffold(
        appBar: AppBar(title: Text('Expanded Widget')),
        body: Row(
          children: [
            Container(width: 100, height: 50, color: Colors.red),
            Expanded(child: Container(height: 50, color: Colors.blue)),
          ],
        ),
      ),
    );
  }
}

In this example, the red container has a fixed width of 100 pixels, while the blue container takes up the remaining horizontal space, thanks to the Expanded widget.

Flutter Expanded Widget
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Expanded Widget',
      home: Scaffold(
        appBar: AppBar(title: Text('Expanded Widget')),
        body: Row(
          children: [
            Expanded(child: Container(color: Colors.red, height: 100)),
            Expanded(child: Container(color: Colors.blue, height: 100)),
          ],
        ),
      ),
    );
  }
}

This makes both containers share the horizontal space equally. Since there are two Expanded widgets, they each take up half of the Row.

Flutter Expanded Widget

How It Works

The parent widget (like Row or Column) controls the direction. Expanded tells its child: “Take up as much space as possible in that direction”.

  • In a Row, the direction is horizontal.
  • In a Column, the direction is vertical.

Expanded forces its child to expand to fill the available space.

Using the flex Property

You can control how space is divided using the flex property. By default, flex is 1. A higher number means the widget gets more space compared to others.

Let’s see what happens when we have multiple Expanded widgets:

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Expanded Widget',
      home: Scaffold(
        appBar: AppBar(title: Text('Expanded Widget')),
        body: Row(
          children: [
            Expanded(flex: 1, child: Container(color: Colors.red, height: 100)),
            Expanded(
              flex: 2,
              child: Container(color: Colors.blue, height: 100),
            ),
          ],
        ),
      ),
    );
  }
}

In this case, the red box gets 1 part and the blue box gets 2 parts of the space. So the blue box is twice as wide as the red one.

Flutter Expanded Widget

Expanded in a Column

Let’s look at Expanded inside a Column, where it grows vertically:

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Expanded Widget',
      home: Scaffold(
        appBar: AppBar(title: Text('Expanded Widget')),
        body: Column(
          children: [
            Text('Above'),
            Expanded(child: Container(color: Colors.green)),
            Text('Below'),
          ],
        ),
      ),
    );
  }
}

Here, the green box expands to fill the space between the top and bottom text widgets.

Flutter Expanded Widget

Expanded vs Flexible

Both Expanded and Flexible are used to make children of a Row, Column, or Flex widget share available space. However, there’s a key difference in how much control they give to their child.

Expanded

  • Forces its child to take all the available space along the main axis (horizontal in a Row, vertical in a Column).
  • The child must fill the space, even if it doesn’t need that much room.

Flexible

  • Allows the child to take as much space as it needs, up to the available space.
  • If the child has a set width or height, it will respect that size but can still grow or shrink as needed.
  • It won’t force the child to stretch if the child can fit without doing so.

Example Comparison

Imagine you have two boxes inside a Row. One is Flexible, and the other is Expanded. Here’s what will happen:

  • The Flexible child, with a width of 100, stays at 100 if there’s enough space.
  • If the space is tight, the Flexible child can shrink or expand to fit.
  • The Expanded child, on the other hand, always stretches to fill up all the remaining space.
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Expanded Widget',
      home: Scaffold(
        appBar: AppBar(title: Text('Expanded Widget')),
        body: Row(
          children: [
            Flexible(flex: 1, child: Container(width: 50, color: Colors.red)),
            Expanded(flex: 1, child: Container(width: 50, color: Colors.blue)),
          ],
        ),
      ),
    );
  }
}

In this example, the red box is wrapped in a Flexible widget and has a fixed width of 50. Since Flexible doesn’t force its child to stretch, the red box maintains its width.

Flutter Expanded Widget

The blue box, however, is wrapped in an Expanded widget. Despite having a width of 50, the Expanded widget forces the box to stretch and take up all the remaining horizontal space, while still leaving room for the Flexible widget to grow if needed. As a result, the blue box ignores its fixed width and expands to fill the rest of the row.

So in short:

  • Use Expanded when you want the widget to fill up all remaining space.
  • Use Flexible when the widget can grow or shrink, but doesn’t have to.

Nested Expanded Widgets

You can nest Expanded inside another Column or Row, just be careful about how much space you are giving at each level.

Here’s an example:

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Expanded Widget',
      home: Scaffold(
        appBar: AppBar(title: Text('Expanded Widget')),
        body: Column(
          children: [
            Expanded(
              child: Row(
                children: [
                  Expanded(child: Container(color: Colors.orange)),
                  Expanded(child: Container(color: Colors.purple)),
                ],
              ),
            ),
            Container(height: 100, color: Colors.black),
          ],
        ),
      ),
    );
  }
}

This layout gives half the screen to a row with two equal boxes, and the bottom box stays fixed at 100 pixels.

Flutter Expanded Widget

Common Error: Expanded Needs Flex Parent

You can only use Expanded inside a Row, Column, or Flex. If you put it somewhere else, you’ll get an error:

Incorrect use of ParentDataWidget.
Typically, Expanded widgets are placed directly inside Flex widgets.

This error occurs when you use Expanded outside of a Row, Column, or Flex. To fix it, ensure that the direct parent of the Expanded widget is one of these flex-based widgets.

When Not to Use Expanded

Avoid using Expanded:

  • Inside a SingleChildScrollView (unless wrapped inside a fixed-height widget like SizedBox).
  • Outside of Row, Column, or Flex.
  • If your layout doesn’t require flexible sizing.

Conclusion

The Expanded widget is a simple yet powerful tool for creating responsive layouts in Flutter. It enables you to fill available space in a Row, Column, or Flex, and the flex property allows you to control how that space is shared among multiple children.

When you need more control over space allocation — for instance, when a widget can grow or shrink as needed but doesn’t have to — you can use Flexible instead.

Once you understand how Expanded works, designing your UI becomes much easier, and your apps will look cleaner and behave more predictably across various screen sizes.

Scroll to Top