Intermediate · Layouts · topic 17 of 50 · 30 min
Row and Column
Explanation
The two workhorses
Almost every screen is built from Rows and Columns nested inside each other. A product card is a Row (image, then text); the text part is a Column (name, price, rating). Once you understand their two axes, most layouts become easy.
Column (main axis: vertical) Row (main axis: horizontal)
┌───────────────┐ ┌──────────────────────────┐
│ [ child 1 ] │ ↓ main axis │ [c1] [c2] [c3] → main │
│ [ child 2 ] │ └──────────────────────────┘
│ [ child 3 ] │ ↔ cross axis ↕ cross axis
└───────────────┘Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: const [
Text('Masala dosa'),
Text('Rs 90'),
],
)| MainAxisAlignment | Effect |
|---|---|
| start (default) | Children packed at the start |
| center / end | Packed in the middle / at the end |
| spaceBetween | First and last at the edges, equal space between |
| spaceAround | Equal space around each child (half-size at the edges) |
| spaceEvenly | Equal space between and at the edges |
crossAxisAlignment options include start, center (default), end and stretch. stretch makes children fill the cross axis, for example full-width buttons in a Column.
A good habit when you look at any design: draw boxes around it. Ask "is this a vertical list of things or a horizontal one?" Mark each group as a Row or a Column, and work from the outside in. A login screen is a Column; inside it, the "Forgot password? Sign up" line is a Row.
Row and Column do not scroll. If their children do not fit, you get an overflow error (topic 4). For content that can be longer than the screen, use a scrolling widget such as ListView or SingleChildScrollView.
mainAxisSize
By default a Column tries to be as tall as its parent allows (mainAxisSize: MainAxisSize.max). Inside a Center, that means the Column fills the screen height and its children sit at the top. MainAxisSize.min makes the Column only as tall as its children, so Center can really centre it.
Spacing between children
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const TextField(decoration: InputDecoration(labelText: 'Name')),
const SizedBox(height: 12), // fixed gap
const TextField(decoration: InputDecoration(labelText: 'Mobile')),
const SizedBox(height: 24),
ElevatedButton(onPressed: () {}, child: const Text('Continue')),
],
)Nesting
Row(
children: [
const Icon(Icons.storefront, size: 40),
const SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text('Sharma General Store'),
Text('Open till 10 pm'),
],
),
],
)Common mistakes
- Wrapping a Column in Center and wondering why it is still at the top: set mainAxisSize: MainAxisSize.min.
- Too many Rows in a narrow screen: text overflows. See topic 4 for fixes with Expanded and Flexible.
- Using spaceBetween with only one child: nothing visible happens.
- Forgetting that crossAxisAlignment.stretch in a Row needs a bounded height.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Row and Column · 1/6
Column stacks children vertically. Row places them side by side.
Prefer a video by a teacher? Find free videos on “flutter row column mainaxisalignment crossaxisalignment tutorial” on YouTube ↗
In real life: A bill summary row
A restaurant billing app shows each line of the bill as "item on the left, amount on the right", with the total in bold at the bottom. A Column of Rows with MainAxisAlignment.spaceBetween does it cleanly, and the same widget works on small and large phones.
class BillLine extends StatelessWidget {
const BillLine(this.label, this.amount, {super.key, this.bold = false});
final String label;
final int amount;
final bool bold;
@override
Widget build(BuildContext context) {
final style = bold ? const TextStyle(fontWeight: FontWeight.bold) : null;
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [Text(label, style: style), Text('Rs $amount', style: style)],
);
}
}
// Column(children: const [BillLine('Thali', 180), BillLine('Lassi', 60), BillLine('Total', 240, bold: true)])Practice (0/3 done)
In a Row, which property controls horizontal spacing between children?
A Column inside Center still appears at the top of the screen. What is the usual fix?
Build a "contact card": a Row with a CircleAvatar on the left and a Column on the right (name in bold, phone, city), and below it a Row of three buttons (Call, SMS, WhatsApp) spaced evenly. Try every MainAxisAlignment value on the button row and note the difference.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Container, Padding, SizedBox, Expanded and FlexibleLayouts · same module
- Stack, Positioned and AlignLayouts · same module
- Understanding constraints and fixing overflowLayouts · same module
- Layouts: Column, Row, Box and ScaffoldKotlin and Android App Development · Jetpack Compose UI
- FlexboxFrontend Web Development · CSS layout and responsive design
- NumPy: fast arrays of numbersData Science, Machine Learning and AI · Cleaning, exploring and visualising data
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
What is the main axis of a Column?
Answer: Vertical
Columns lay out vertically.
Which MainAxisAlignment puts equal space between children and at both edges?
Answer: spaceEvenly
spaceEvenly also spaces the edges.
What does crossAxisAlignment: CrossAxisAlignment.stretch do in a Column?
Answer: Stretches children to fill the width
For a Column the cross axis is horizontal.
Which widget is commonly used for a fixed gap between children?
Answer: SizedBox
SizedBox(height: 12) or SizedBox(width: 12).
Is nesting Rows and Columns expensive in Compose?Related
Answer: No, nesting is cheap; write clear code
Compose measures each child once.
In a row, which property centres items vertically?Related
Answer: align-items
In a row the cross axis is vertical, and align-items works on the cross axis.
From Flexbox
m has shape (100, 5): 100 customers, 5 features. What shape does m.mean(axis=0) have?Related
Answer: (5,)
axis=0 collapses the rows, leaving one mean per column: 5 values.
Which property lets children draw outside the Stack's bounds?Related
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 4 more topics in “Layouts” before its exam: Container, Padding, SizedBox, Expanded and Flexible, Stack, Positioned and Align, Understanding constraints and fixing overflow, Images, icons, fonts and themes.
- Module 5 exam: Layouts · 13 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Lists, navigation and forms. 50 topics left in the course before the final exam.