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
| Widget | Main Axis | Cross Axis |
|---|---|---|
| Row | Horizontal ↔ | Vertical ↕ |
| Column | Vertical ↕ | 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
| Mistake | Fix |
|---|---|
| Column inside Column causes overflow | Wrap outer Column in SingleChildScrollView |
| Row children overflow screen width | Use Flexible or Wrap |
| Stack child with no size defined | Use Positioned or set width/height on child |
| Row has both Expanded and fixed-size children fighting for space | Only wrap the child that should grow in Expanded |
