Sizing widgets relative to parent/screen size in Flutter

Share this post

Oftentimes we don’t want our widgets to have a specific width or height, but rather have a width or height that is relative to the parent. For instance, we want a container to take 65% of the screen width or two containers that each taking respectively 70% and 30% of parent width. These are just 2 examples off the top of my head, but once you learn the basics, you can apply it to every case.

Sizing a widget relative to screen size

To be able to do this, we need to know the size of the device screen. No worries, Flutter has just the widget for that. To get the screen size just do the following:

MediaQuery.of(context).size // contains width and height

And use it anywhere in your app. Let’s say we want to have a container with width and height that are half as large as the screen. We would end up with the following code.

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("MediaQuery"),
      ),
      body: Container(
        width: MediaQuery.of(context).size.width * 0.5,
        height: MediaQuery.of(context).size.height * 0.5,
      ),
    );
  }

But what if we want to have a container that takes half of the available space (means half of the parent widget)? Enter FractionallySizedBox!

Sizing a widget relative to its parent

FractionallySizedBox is a widget (a container) that lets its child have a widthFactor and a heightFactor. You can see this as a kind of scale value. So if we want to have a container that takes half of the available space horizontally and vertically, we would do the following:

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("FractionallySizedBox"),
      ),
      body: FractionallySizedBox(
        widthFactor: 0.5,
        heightFactor: 0.5,
        child: Container(
          // this container won't be larger than
          // half of its parent size
        ),
      ),
    );
  }

What if we have a list of widgets that we want to place next to each other horizontally or vertically and we want them to take a certain percentage of the list. We can do just that using Expanded.

Sizing a list of widgets relative to each other

By using expanded and setting the flex property, we can give each widget in a Row or Column its own weight (I explained Row and Column in one of my earlier posts). That means how much of the available space of that widget it is allowed to fill. So we can have the following code for a horizontal alignment:

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Expanded"),
      ),
      body: Container(
        child: Row(
          children: <Widget>[
            Expanded(
              flex: 6, // 60% of space => (6/(6 + 4))
              child: Container(
                color: Colors.red,
              ),
            ),
            Expanded(
              flex: 4, // 40% of space
              child: Container(
                color: Colors.purple,
              ),
            ),
          ],
        ),
      ),
    );
  }

By default, Expanded takes the whole available space, so if we want 2 widgets to take 50% of the space, we can remove the flex property altogether.

There are more ways to size widgets relative to a parent widget, I just described the most common ways. If you know more ways to do this, let me know in the comment section.