Flutter Lesson 15 of 83 3 min read
Row and Column in Flutter
Learn Row and Column in Flutter: arrange widgets horizontally and vertically with mainAxisAlignment, crossAxisAlignment and spacing.
On this page
Row places its children side by side. Column stacks them top to bottom. Between them they handle most layouts.
Main axis and cross axis #
| Main axis | Cross axis | |
|---|---|---|
Row | Horizontal | Vertical |
Column | Vertical | Horizontal |
mainAxisAlignment positions children along the direction of flow. crossAxisAlignment positions them across it.
Try the alignments #
import 'package:flutter/material.dart';
class Box extends StatelessWidget {
const Box(this.color, {super.key});
final Color color;
@override
Widget build(BuildContext context) =>
Container(width: 56, height: 56, color: color);
}
void main() {
runApp(
const MaterialApp(
home: Scaffold(
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [Box(Colors.red), Box(Colors.green), Box(Colors.blue)],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [Box(Colors.red), Box(Colors.green), Box(Colors.blue)],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [Box(Colors.red), Box(Colors.green), Box(Colors.blue)],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [Box(Colors.red), Box(Colors.green), Box(Colors.blue)],
),
],
),
),
),
),
);
}
MainAxisAlignment | Effect |
|---|---|
start | Packed at the start (the default) |
end | Packed at the end |
center | Packed in the middle |
spaceBetween | First and last at the edges, equal gaps between |
spaceAround | Equal gaps, with half-size gaps at the edges |
spaceEvenly | Equal gaps everywhere, including the edges |
Cross axis alignment #
CrossAxisAlignment | Effect |
|---|---|
center | Centred (the default) |
start | At the start: left for a column, top for a row |
end | At the end |
stretch | Children are forced to fill the cross axis |
A Column centres its children horizontally by default, which is rarely what you want for text. Left-align them:
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text('Order #1042'),
Text('3 items'),
Text('Delivered'),
],
)
mainAxisSize #
By default a row or column takes all the space on its main axis. Set mainAxisSize: MainAxisSize.min to make it only as big as its children. You need this to centre a column on the screen or to put one inside a card.
Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: const [Icon(Icons.inbox, size: 48), Text('No messages yet')],
),
)
Spacing between children #
Recent versions of Flutter have a spacing parameter:
Row(
spacing: 12,
children: const [Icon(Icons.star), Text('4.8'), Text('(120 reviews)')],
)
On older versions, or for different gaps, put SizedBox widgets between the children:
Column(
children: const [
Text('Title'),
SizedBox(height: 8),
Text('Subtitle'),
SizedBox(height: 24),
Text('Body'),
],
)
const Spacer() takes up all the free space, pushing what follows to the far end.
Row(
children: [
const Text('Total'),
const Spacer(),
const Text('Rs. 1,499'),
],
)
Nesting rows and columns #
Real layouts are rows inside columns inside rows.
Row(
children: [
const CircleAvatar(child: Text('A')),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text('Asha Rai', style: TextStyle(fontWeight: FontWeight.bold)),
Text('See you at 5?', maxLines: 1, overflow: TextOverflow.ellipsis),
],
),
),
const Text('14:20'),
],
)
Rows and columns do not scroll #
Too many children cause an overflow error. For content that may not fit, use a ListView, or wrap the column in a SingleChildScrollView. For items that should flow onto the next line, use Wrap.
Try it yourself #
Build a settings row: an icon on the left, a title with a subtitle beneath it, and a Switch on the far right. Then put three such rows in a column with dividers between them.