Flutter

Padding, Margin, Column & Row

Padding widget vs EdgeInsets, Container margin vs padding, Column mainAxisAlignment, Row crossAxisAlignment, Expanded, Flexible, Spacer, and Wrap.

Padding Widget & EdgeInsets

The Padding widget adds space around a child. EdgeInsets provides multiple constructors for specifying padding values.

Dart
// All sides equal
Padding(
  padding: const EdgeInsets.all(16),
  child: Text('All sides 16px'),
)

// Horizontal and vertical
Padding(
  padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
  child: Text('Symmetric padding'),
)

// Individual sides
Padding(
  padding: const EdgeInsets.only(top: 8, left: 16, bottom: 4),
  child: Text('Specific sides'),
)

// Respond to device text scaling
Padding(
  padding: EdgeInsets.fromLTRB(16, 8, 16, 0),
  child: Text('From LTRB'),
)

// Using EdgeInsetsDirectional (respects RTL)
Padding(
  padding: const EdgeInsetsDirectional.only(start: 16, end: 8),
  child: Text('RTL-aware padding'),
)

Container: margin vs padding

margin adds space outside the container's border, while padding adds space inside (between the border and the child content).

Dart
Container(
  margin: const EdgeInsets.all(16),   // outside: space from surrounding widgets
  padding: const EdgeInsets.all(12),  // inside: space between border and child
  decoration: BoxDecoration(
    color: Colors.blue[50],
    borderRadius: BorderRadius.circular(12),
    border: Border.all(color: Colors.blue),
    boxShadow: [
      BoxShadow(
        color: Colors.black.withOpacity(0.1),
        blurRadius: 8,
        offset: const Offset(0, 4),
      ),
    ],
  ),
  width: double.infinity,
  child: const Text('I have both margin and padding'),
)

// Common shorthand: wrap Text directly in Padding for no background
const Padding(
  padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
  child: Text('No background needed'),
)

Column & mainAxisAlignment

Column stacks children vertically. mainAxisAlignment controls vertical distribution; crossAxisAlignment controls horizontal alignment.

Dart
// mainAxisAlignment options
Column(
  mainAxisAlignment: MainAxisAlignment.center,       // center vertically
  // MainAxisAlignment.start      – top (default)
  // MainAxisAlignment.end        – bottom
  // MainAxisAlignment.spaceBetween – equal space between items
  // MainAxisAlignment.spaceAround  – equal space around items
  // MainAxisAlignment.spaceEvenly  – equal space including edges
  crossAxisAlignment: CrossAxisAlignment.start,
  // CrossAxisAlignment.center (default)
  // CrossAxisAlignment.end
  // CrossAxisAlignment.stretch – fill full width
  children: [
    Container(color: Colors.red,   width: 80,  height: 40),
    Container(color: Colors.green, width: 120, height: 40),
    Container(color: Colors.blue,  width: 60,  height: 40),
  ],
)

// Column with mainAxisSize to wrap content height
Column(
  mainAxisSize: MainAxisSize.min, // shrink-wrap children
  children: const [
    Text('Line 1'),
    Text('Line 2'),
  ],
)

Row & crossAxisAlignment

Row places children horizontally. mainAxisAlignment controls horizontal distribution; crossAxisAlignment controls vertical alignment.

Dart
Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  crossAxisAlignment: CrossAxisAlignment.center,
  children: [
    const Icon(Icons.star, size: 32),
    const Text('Flutter', style: TextStyle(fontSize: 20)),
    ElevatedButton(
      onPressed: () {},
      child: const Text('Get Started'),
    ),
  ],
)

// Row with baseline alignment for mixed text sizes
Row(
  crossAxisAlignment: CrossAxisAlignment.baseline,
  textBaseline: TextBaseline.alphabetic,
  children: const [
    Text('100', style: TextStyle(fontSize: 36, fontWeight: FontWeight.bold)),
    SizedBox(width: 4),
    Text('USD', style: TextStyle(fontSize: 14, color: Colors.grey)),
  ],
)

Expanded, Flexible & Spacer

Expanded forces a child to fill remaining space. Flexible allows a child to take available space but can be smaller. Spacer pushes siblings apart.

Dart
// Expanded – forces full remaining space
Row(
  children: [
    const Icon(Icons.label),
    const SizedBox(width: 8),
    Expanded(
      child: Text(
        'Very long text that would overflow without Expanded',
        overflow: TextOverflow.ellipsis,
      ),
    ),
    const Icon(Icons.chevron_right),
  ],
)

// Flexible flex ratios (2:1 split)
Row(
  children: [
    Expanded(
      flex: 2, // takes 2/3 of space
      child: Container(color: Colors.blue, height: 50),
    ),
    Expanded(
      flex: 1, // takes 1/3 of space
      child: Container(color: Colors.red, height: 50),
    ),
  ],
)

// Flexible – can be smaller than available space
Row(
  children: [
    Flexible(
      child: Text('Short'), // won't be forced to fill
    ),
    Flexible(
      child: Text('Also short'),
    ),
  ],
)

// Spacer – pushes items to opposite ends
Row(
  children: [
    const Text('Left'),
    const Spacer(),     // fills remaining space between
    const Text('Right'),
  ],
)

// Spacer with flex
Row(
  children: [
    const Text('A'),
    const Spacer(flex: 2),
    const Text('B'),
    const Spacer(flex: 1),
    const Text('C'),
  ],
)

Wrap Widget

Wrap is like a Row or Column that automatically wraps overflowing children onto the next line. Great for tags, chips, and button groups.

Dart
// Wrap for tag chips
Wrap(
  spacing: 8,          // horizontal gap between children
  runSpacing: 8,       // vertical gap between lines
  alignment: WrapAlignment.start,
  // WrapAlignment.center, .end, .spaceAround, .spaceBetween, .spaceEvenly
  children: [
    'Flutter', 'Dart', 'Android', 'iOS', 'Web', 'Desktop',
  ].map((tag) => Chip(label: Text(tag))).toList(),
)

// Wrap with direction column (wraps into columns)
Wrap(
  direction: Axis.vertical,
  spacing: 4,
  runSpacing: 16,
  children: [
    Container(width: 80, height: 30, color: Colors.red),
    Container(width: 80, height: 30, color: Colors.green),
    Container(width: 80, height: 30, color: Colors.blue),
  ],
)

// Wrap for responsive button row
Wrap(
  spacing: 8,
  runSpacing: 8,
  children: [
    ElevatedButton(onPressed: () {}, child: const Text('Save')),
    OutlinedButton(onPressed: () {}, child: const Text('Cancel')),
    TextButton(onPressed: () {}, child: const Text('Preview')),
  ],
)