// Tutorial //

Creating a Basic Layout in Flutter

Published on September 6, 2019
Default avatar
By Joshua Hall
Developer and author at DigitalOcean.
Creating a Basic Layout in Flutter

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

As Flutter quickly becomes one of the leading technologies in app development, it is important for even someone in the web dev environment to check out. Coming from a background of HTML, CSS and JavaScript, the way Flutter handled everything seemed extremely foreign to me. So we’re going to be try and simplify it to just the essentials of structuring the elements in our app to create a simple layout using the Material Components.

Prerequisites

Already having Flutter installed and an emulator set up is necessary, we covered getting started in Flutter here. Becoming familiar with the official docs is also always a plus.

Scaffold

The Scaffold instantiates our main structure, usually whatever is consistent across our app like our appbar or navigation, then we’ll set our body to the more interesting part of our app, abstracting it out of runApp will also allow us to use hot reload.

main.dart
import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          centerTitle: true,
          title: Text('I\'m an App'),
          backgroundColor: Colors.red[600],
        ),
        body: App(),
      ),
    ),
  );
}

class App extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Container();
  }
}

And here’s what this looks like:

Scaffold

Containers

Like with HTML div’s, we can wrap our containers to give us more control over our elements when we can’t manipulate them themselves, since not every widget has properties like width or padding. Containers have some of the same properties from CSS like height, width, padding, and margin. By default, they will take up the maximum space of their children, empty containers try to take up the maximum amount of space of their parent.

Margin and Padding

Controlling the spacing can be a bit weird, instead of directly setting padding or margin to a number of pixels, we need to set it to a property on EdgeInsets and pass in our value in pixels. There is also the Padding widget that you can wrap your elements in, but you still need to pass-in padding the same as before so it’s really just to be explicit.

  • EdgeInsets.all()
  • EdgeInsets.only(left: 0, top: 0, right: 0, bottom: 0)
  • EdgeInsets.symmetric(vertical: 0, horizontal: 0)
  • EdgeInsets.fromLTRB(left, top, right, bottom) Just takes the values without them be explicitly assigned.
main.dart
class App extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Container(
      color: Colors.blue,
      margin: EdgeInsets.only(top: 20, right: 50),
      child: Container(
        color: Colors.green,
        // Add 200px on top and bottom
        margin: EdgeInsets.symmetric(vertical: 200),
        child: Container(
          color: Colors.yellow,
          margin: EdgeInsets.fromLTRB(0, 20, 200, 20),
        ),
      ),
    );
  }
}

And now we have a bunch of containers:

Screenshot of container

Columns and Rows

The problem with containers is that we can only have one child in each. The column and row widgets let us use a more flexible version of containers while controlling the direction of our elements. We can’t just pass child to them for each element, we need to set children to an array of the type <Widget>, then pass in each of our elements.

If we put a container inside of an Expanded widget, it will then take up the maximum amount of space of its column or row.

Similar to how flexbox works on the web, we can use mainAxisAlignment and crossAxisAlignment to do things the same as justify-content and align-items. We even have the same options of start, center, end, spaceEvenly, spaceAround, spaceBetween, and stretch.

main.dart
class App extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: <Widget>[
          // Row 1
          Row(
            children: <Widget>[
              Container(
                color: Colors.blue, height: 40, width: 40, child: Text('1')),
              Container(
                color: Colors.blue, height: 40, width: 40, child: Text('2')),
              Container(
                color: Colors.blue, height: 40, width: 40, child: Text('3')),
            ],
          ),
          // Row 2
          Row(
            children: <Widget>[
              Container(
                color: Colors.blue, height: 40, width: 40, child: Text('1')),
              //Will expand to fill all remaining space
              Expanded(
                  child: Container(
                    color: Colors.green,
                    height: 40,
                    width: 40,
                    child: Text('2'))),
              Container(
                color: Colors.blue, height: 40, width: 40, child: Text('3')),
            ],
          ),
          //Row 3
          Container(
              height: 100,
              child: Row(
                //Stretches to vertically fill its parent container
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: <Widget>[
                  Container(
                    color: Colors.blue,
                    height: 40,
                    width: 40,
                    child: Text('1')),
                  Expanded(
                      child: Container(
                        color: Colors.green,
                        height: 40,
                        width: 40,
                        child: Text('2'))),
                  Container(
                    color: Colors.blue,
                    height: 40,
                    width: 40,
                    child: Text('3')),
                ],
              )),
          // Row 4
          Row(
            //Creates even space between each item and their parent container
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              Container(
                color: Colors.blue, height: 40, width: 40, child: Text('1')),
              Container(
                color: Colors.blue, height: 40, width: 40, child: Text('1')),
              Container(
                color: Colors.blue, height: 40, width: 40, child: Text('3')),
            ],
          )
        ]);
  }
}

And here’s a screenshot of our rows and columns:

Screenshot of columns and Rows

Conclusion

While working with layouts in Flutter may seem a bit more clunky and verbose that on the web at first glance, it’s good to keep in mind that we also don’t have to deal with the complexity of dynamic grids or bloated media queries for every screen size. At times, layouts in Flutter may seem less powerful than the CSS you’re used to, because it really doesn’t have to be. With just a few containers, columns, rows, and spacing you can get most of the structures than you’ll ever need.


Want to learn more? Join the DigitalOcean Community!

Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in our Questions & Answers section, find tutorials and tools that will help you grow as a developer and scale your project or business, and subscribe to topics of interest.

Sign up
About the authors
Default avatar
Developer and author at DigitalOcean.

Still looking for an answer?

Was this helpful?
Leave a comment

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!