Flutter Layouts Row Column Stack

Layout widgets control how children are positioned on screen. Row, Column, and Stack are the three core layout tools in Flutter. Master these and you can build almost any screen design.

Row — Horizontal Layout

A Row places its children side by side from left to right.

  Row:
  ┌────────────────────────────────────┐
  │ [Child 1] [Child 2] [Child 3]      │
  └────────────────────────────────────┘
Row(
  children: [
    Icon(Icons.star, color: Colors.yellow),
    Text('4.8'),
    Text('(200 reviews)'),
  ],
)

Row Alignment

Two axes control Row alignment: mainAxis (horizontal) and crossAxis (vertical).

  mainAxisAlignment (horizontal ↔):
  ──────────────────────────────────────────
  start   → [A] [B] [C] . . . . . . . . .
  center  → . . . . [A] [B] [C] . . . . .
  end     → . . . . . . . . . [A] [B] [C]
  spaceBetween → [A] . . . . . [B] . . . [C]
  spaceAround  → . [A] . . [B] . . [C] .
  spaceEvenly  → . [A] . . [B] . . [C] .

  crossAxisAlignment (vertical ↕):
  ──────────────────────────────────────────
  start   → children align to the top
  center  → children align to the middle
  end     → children align to the bottom
Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  crossAxisAlignment: CrossAxisAlignment.center,
  children: [
    Text('Name'),
    Text('Price'),
    Text('Qty'),
  ],
)

Column — Vertical Layout

A Column stacks its children top to bottom. The axes flip compared to Row: mainAxis is now vertical, crossAxis is horizontal.

  Column:
  ┌──────────────────────┐
  │ [Child 1]            │
  │ [Child 2]            │
  │ [Child 3]            │
  └──────────────────────┘
Column(
  mainAxisAlignment: MainAxisAlignment.center,
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    Text('Flutter Course', style: TextStyle(fontSize: 22)),
    SizedBox(height: 8),
    Text('Learn mobile development'),
    SizedBox(height: 16),
    ElevatedButton(onPressed: () {}, child: Text('Start')),
  ],
)

Row vs Column — Axis Reference

WidgetMain AxisCross Axis
RowHorizontal ↔Vertical ↕
ColumnVertical ↕Horizontal ↔

Expanded and Flexible

By default, Row and Column give each child only the space it needs. Use Expanded to make a child fill the remaining space.

  Without Expanded:
  [Button1][Button2] . . . . . (empty space wasted)

  With Expanded:
  [────── Button1 ──────][Button2]  (fills the space)
Row(
  children: [
    Expanded(child: ElevatedButton(onPressed: () {}, child: Text('Save'))),
    SizedBox(width: 8),
    ElevatedButton(onPressed: () {}, child: Text('Cancel')),
  ],
)

Flexible is similar but lets the child shrink below its ideal size if space is tight.

Stack — Layered Layout

A Stack places widgets on top of each other, like sheets of paper stacked in a pile. The first child sits at the bottom; the last sits on top.

  Stack (viewed from the side):

  Layer 3 (top):    ░░░░░ Text "SALE" badge
  Layer 2 (middle): ▒▒▒▒▒ Discount label
  Layer 1 (bottom): █████ Product image
Stack(
  children: [
    // Background image
    Image.network('https://example.com/product.jpg'),

    // Positioned badge on top
    Positioned(
      top: 10,
      right: 10,
      child: Container(
        color: Colors.red,
        padding: EdgeInsets.all(6),
        child: Text('SALE', style: TextStyle(color: Colors.white)),
      ),
    ),
  ],
)

Positioned Widget

Use Positioned inside a Stack to place a child at an exact location.

  Stack bounding box:
  ┌────────────────────────────┐
  │                      ┌───┐ │  ← top:10, right:10
  │                      │SALE │
  │                      └───┘ │
  │     [Product Image]        │
  └────────────────────────────┘

Wrapping Long Lists — Wrap Widget

When children overflow a Row, use Wrap instead. It automatically moves extra items to a new line.

Wrap(
  spacing: 8,
  runSpacing: 4,
  children: [
    Chip(label: Text('Flutter')),
    Chip(label: Text('Dart')),
    Chip(label: Text('Firebase')),
    Chip(label: Text('Provider')),
    Chip(label: Text('REST API')),
  ],
)
  ┌──────────────────────────────────────┐
  │ [Flutter] [Dart] [Firebase]          │
  │ [Provider] [REST API]                │
  └──────────────────────────────────────┘

ListView — Scrollable Column

When a Column's content is taller than the screen, Flutter throws an overflow error. Wrap it in a ListView to make it scrollable.

ListView(
  children: [
    ListTile(title: Text('Item 1')),
    ListTile(title: Text('Item 2')),
    ListTile(title: Text('Item 3')),
    // Add as many as needed — scrolls automatically
  ],
)

Common Layout Mistakes

MistakeFix
Column inside Column causes overflowWrap outer Column in SingleChildScrollView
Row children overflow screen widthUse Flexible or Wrap
Stack child with no size definedUse Positioned or set width/height on child
Row has both Expanded and fixed-size children fighting for spaceOnly wrap the child that should grow in Expanded

Leave a Comment

Your email address will not be published. Required fields are marked *