Overview

Column is a layout widget that arranges its children in a vertical direction.

Column is a convenience wrapper around the Flex widget with the direction fixed to vertical. It’s used to place multiple widgets one below another and provides various alignment options. By default, Column takes up all available vertical space, but you can adjust mainAxisSize to only take up as much space as needed.

When to use it?

  • When arranging form fields vertically
  • When structuring content in list items
  • When creating vertical layouts for cards or dialogs
  • When arranging menu items vertically
  • When displaying title, subtitle, and body text in sequence

Basic Usage

// Simple example
const column = Column({
  children: [
    Text('Title'),
    Text('Subtitle'),
    Text('Body')
  ]
});

// Using alignment options
const alignedColumn = Column({
  mainAxisAlignment: MainAxisAlignment.center,
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    Text('Left aligned'),
    Text('Vertically centered'),
    Text('Text widgets')
  ]
});

Props

children (required)

Value: Widget[]

An array of child widgets to display in the Column. They are arranged from top to bottom in array order.

Column({
  children: [
    Container({ width: 100, height: 50, color: 'red' }),
    Container({ width: 100, height: 50, color: 'green' }),
    Container({ width: 100, height: 50, color: 'blue' })
  ]
})

mainAxisAlignment

Value: MainAxisAlignment (default: MainAxisAlignment.start)

Defines the vertical alignment of child widgets.

  • start: Top alignment (default)
  • end: Bottom alignment
  • center: Center alignment
  • spaceBetween: Place first and last widgets at edges, distribute remaining space evenly
  • spaceAround: Distribute equal space around each widget
  • spaceEvenly: Distribute equal space between all widgets and edges
// Center alignment
Column({
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    Text('A'),
    Text('B'),
    Text('C')
  ]
})

// Space evenly
Column({
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: [
    Icon({ icon: Icons.home }),
    Icon({ icon: Icons.search }),
    Icon({ icon: Icons.settings })
  ]
})

crossAxisAlignment

Value: CrossAxisAlignment (default: CrossAxisAlignment.center)

Defines the horizontal alignment of child widgets.

  • start: Left alignment
  • end: Right alignment
  • center: Horizontal center alignment (default)
  • stretch: Stretch to fill available horizontal space
Column({
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    Container({ width: 100, height: 50, color: 'red' }),
    Container({ width: 150, height: 50, color: 'green' }),
    Container({ width: 75, height: 50, color: 'blue' })
  ]
})

mainAxisSize

Value: MainAxisSize (default: MainAxisSize.max)

Controls the amount of vertical space the Column takes up.

  • max: Take up all available vertical space (default)
  • min: Take up only the minimum space needed by children
// Take up only necessary space
Container({
  color: 'lightgray',
  child: Column({
    mainAxisSize: MainAxisSize.min,
    children: [
      Text('Compact'),
      Text('Column')
    ]
  })
})

verticalDirection

Value: VerticalDirection (default: VerticalDirection.down)

Defines the vertical layout order of child widgets.

  • down: From top to bottom (default)
  • up: From bottom to top
Column({
  verticalDirection: VerticalDirection.up,
  children: [
    Text('1st'), // Displayed at bottom
    Text('2nd'), // Displayed in middle
    Text('3rd')  // Displayed at top
  ]
})

Advanced Usage

Using with Expanded

Column({
  children: [
    Container({ width: 100, height: 50, color: 'red' }),
    Expanded({
      child: Container({ width: 100, color: 'green' })
    }),
    Container({ width: 100, height: 50, color: 'blue' })
  ]
})
// The green Container takes up all remaining vertical space

Proportional Space Distribution

Column({
  children: [
    Flexible({
      flex: 1,
      child: Container({ color: 'red' })
    }),
    Flexible({
      flex: 2,
      child: Container({ color: 'green' })
    }),
    Flexible({
      flex: 1,
      child: Container({ color: 'blue' })
    })
  ]
})
// Red takes 25%, green takes 50%, blue takes 25% of height

Practical Examples

Example 1: Login Form

const loginForm = Container({
  padding: EdgeInsets.all(20),
  child: Column({
    mainAxisAlignment: MainAxisAlignment.center,
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: [
      Text('Login', {
        style: TextStyle({ fontSize: 24, fontWeight: 'bold' })
      }),
      SizedBox({ height: 30 }),
      TextField({
        decoration: InputDecoration({
          labelText: 'Email',
          border: OutlineInputBorder()
        })
      }),
      SizedBox({ height: 16 }),
      TextField({
        obscureText: true,
        decoration: InputDecoration({
          labelText: 'Password',
          border: OutlineInputBorder()
        })
      }),
      SizedBox({ height: 24 }),
      ElevatedButton({
        onPressed: () => console.log('Login'),
        child: Text('Login')
      }),
      SizedBox({ height: 16 }),
      TextButton({
        onPressed: () => console.log('Sign up'),
        child: Text("Don't have an account? Sign up")
      })
    ]
  })
});

Example 2: Card Content

const card = Container({
  margin: EdgeInsets.all(16),
  padding: EdgeInsets.all(16),
  decoration: BoxDecoration({
    color: 'white',
    borderRadius: BorderRadius.circular(12),
    boxShadow: [
      BoxShadow({
        color: 'rgba(0, 0, 0, 0.1)',
        blurRadius: 10,
        offset: { x: 0, y: 4 }
      })
    ]
  }),
  child: Column({
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      Image({
        src: 'product.jpg',
        height: 200,
        fit: 'cover'
      }),
      SizedBox({ height: 16 }),
      Text('Product Name', {
        style: TextStyle({ fontSize: 20, fontWeight: 'bold' })
      }),
      SizedBox({ height: 8 }),
      Text('Product description goes here...', {
        style: TextStyle({ color: 'gray' })
      }),
      SizedBox({ height: 16 }),
      Row({
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text('$25.00', {
            style: TextStyle({ fontSize: 18, fontWeight: 'bold', color: 'blue' })
          }),
          IconButton({
            icon: Icons.favorite_border,
            onPressed: () => {}
          })
        ]
      })
    ]
  })
});

Example 3: Settings Menu

const settingsMenu = Column({
  children: [
    ListTile({
      leading: Icon({ icon: Icons.person }),
      title: Text('Profile'),
      trailing: Icon({ icon: Icons.arrow_forward_ios }),
      onTap: () => console.log('Profile')
    }),
    Divider(),
    ListTile({
      leading: Icon({ icon: Icons.notifications }),
      title: Text('Notifications'),
      trailing: Switch({
        value: true,
        onChanged: (value) => {}
      })
    }),
    Divider(),
    ListTile({
      leading: Icon({ icon: Icons.lock }),
      title: Text('Privacy'),
      trailing: Icon({ icon: Icons.arrow_forward_ios }),
      onTap: () => console.log('Privacy')
    }),
    Divider(),
    ListTile({
      leading: Icon({ icon: Icons.help }),
      title: Text('Help'),
      trailing: Icon({ icon: Icons.arrow_forward_ios }),
      onTap: () => console.log('Help')
    })
  ]
});

Important Notes

  • If child widgets exceed vertical space, an overflow error occurs. Use SingleChildScrollView or Flexible/Expanded in such cases.
  • When using crossAxisAlignment.stretch, child widgets can expand infinitely if their width is unconstrained.
  • Column doesn’t support scrolling. Use SingleChildScrollView or ListView if scrolling is needed.
  • Use the Row widget for horizontal layouts.
  • Row: Arranges children horizontally
  • Flex: More flexible layout widget that Column and Row are based on
  • ListView: Scrollable vertical list
  • Stack: Overlays children on top of each other
  • Expanded: Takes up remaining space within a Column
  • Flexible: Allows flexible sizing within a Column