Dart Tutorial

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 axisCross axis
RowHorizontalVertical
ColumnVerticalHorizontal

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)],
              ),
            ],
          ),
        ),
      ),
    ),
  );
}
MainAxisAlignmentEffect
startPacked at the start (the default)
endPacked at the end
centerPacked in the middle
spaceBetweenFirst and last at the edges, equal gaps between
spaceAroundEqual gaps, with half-size gaps at the edges
spaceEvenlyEqual gaps everywhere, including the edges

Cross axis alignment #

CrossAxisAlignmentEffect
centerCentred (the default)
startAt the start: left for a column, top for a row
endAt the end
stretchChildren 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.

Practise in the playground Updated by Santosh Adhikari