Container, Padding & SizedBox
Spacing, Sizing, and Decoration
Open interactive version (quiz + challenge)Real-world analogy
What is it?
Container, Padding, and SizedBox are the core spacing and decoration widgets in Flutter. Container is a multi-purpose widget that combines sizing, padding, margin, and decoration. Padding adds space around a child. SizedBox creates fixed-size gaps or constrains dimensions. Together they control the spacing, sizing, and visual styling of your layout.
Real-world relevance
In team_mvp_kit, these widgets appear everywhere. SizedBox is the standard spacer between form fields and buttons. Container with BoxDecoration creates card-like surfaces with rounded corners and shadows. Padding wraps screen content to add consistent horizontal margins. The design system defines standard spacing constants (4, 8, 12, 16, 24, 32) used across all screens.
Key points
- Container Widget — Container is a convenience widget that combines sizing, padding, margin, decoration, alignment, and color into one widget. It is one of the most used widgets in Flutter. When you need to add background color, borders, rounded corners, or specific dimensions to a widget, Container is your go-to.
- Padding Widget — Padding is a single-purpose widget that adds empty space around its child. Unlike Container, it ONLY does padding — nothing else. Use Padding when you just need spacing and do not need decoration, color, or sizing. It is more readable and efficient than an empty Container with only padding set.
- SizedBox for Spacing — SizedBox creates a box with a fixed width and height. Its most common use is as a spacer between widgets — SizedBox(height: 16) adds a 16-pixel vertical gap in a Column, and SizedBox(width: 8) adds an 8-pixel horizontal gap in a Row. It is lighter than Container for pure spacing.
- EdgeInsets Variants — EdgeInsets defines padding or margin amounts. EdgeInsets.all(16) sets 16px on all sides. EdgeInsets.symmetric(horizontal: 16, vertical: 8) sets different horizontal and vertical values. EdgeInsets.only(left: 16, top: 8) sets individual sides. EdgeInsets.fromLTRB(left, top, right, bottom) sets all four explicitly.
- BoxDecoration — BoxDecoration controls the visual appearance of a Container: background color, border, border radius (rounded corners), gradient, box shadow, and background image. Assign it to Container's decoration property. Note: you cannot use both color and decoration — put the color inside the BoxDecoration instead.
- Margin vs Padding — Padding is space INSIDE the container, between its border and its child. Margin is space OUTSIDE the container, between its border and neighboring widgets. Think of it like a picture frame: padding is the mat board inside the frame, margin is the wall space between frames.
- SizedBox.expand and SizedBox.shrink — SizedBox.expand() creates a box that fills all available space in its parent — useful for making a child stretch to fill a container. SizedBox.shrink() creates a zero-sized box — useful as a placeholder when you conditionally want to show nothing without using an empty Container.
- ConstrainedBox and Limits — ConstrainedBox imposes min and max size constraints on its child. Use it when you want a widget to be at least a certain size or no larger than a maximum. BoxConstraints defines the minWidth, maxWidth, minHeight, and maxHeight that the child must respect.
- DecoratedBox vs Container — DecoratedBox is a lightweight widget that only applies a BoxDecoration — no padding, margin, or sizing. If you only need decoration without other Container features, DecoratedBox is more efficient. Container actually wraps DecoratedBox, Padding, Align, and other widgets internally.
Code example
import 'package:flutter/material.dart';
class ProductCard extends StatelessWidget {
final String title;
final String price;
final String imageUrl;
const ProductCard({
super.key,
required this.title,
required this.price,
required this.imageUrl,
});
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.08),
blurRadius: 12,
offset: const Offset(0, 4),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ClipRRect(
borderRadius: const BorderRadius.vertical(
top: Radius.circular(16),
),
child: Image.network(
imageUrl,
height: 180,
width: double.infinity,
fit: BoxFit.cover,
),
),
Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: Theme.of(context).textTheme.titleMedium
?.copyWith(fontWeight: FontWeight.w600),
),
const SizedBox(height: 8),
Text(
price,
style: Theme.of(context).textTheme.titleLarge
?.copyWith(
color: Colors.green.shade700,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 12),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {},
child: const Text('Add to Cart'),
),
),
],
),
),
],
),
);
}
}Line-by-line walkthrough
- 1. Import the Material package
- 2.
- 3. Define ProductCard as a StatelessWidget
- 4. Declare required string fields for title, price, and image URL
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11. Build method creates the widget tree
- 12.
- 13. Return a Container as the outer wrapper
- 14. Margin of 8px on all sides separates cards from each other
- 15. BoxDecoration defines the visual style
- 16. Use the theme's surface color for the background
- 17. 16px border radius for rounded corners
- 18. BoxShadow list for the drop shadow effect
- 19. Black at 8% opacity for a subtle shadow
- 20. 12px blur radius for soft edges
- 21. Offset 0 horizontal, 4 vertical for shadow below the card
- 22.
- 23.
- 24. Column stacks image and text content vertically
- 25. Left-align all children
- 26.
- 27. ClipRRect clips the image to match rounded top corners
- 28. Only round the top corners (top-left and top-right)
- 29.
- 30. Image.network loads the image from a URL
- 31. Fixed height of 180px
- 32. Width fills the container
- 33. BoxFit.cover scales and crops to fill the area
- 34.
- 35.
- 36. Padding wraps the text content section
- 37. 16px padding on all sides
- 38. Inner Column for text content
- 39. Left-align text
- 40.
- 41. Title text with titleMedium style
- 42. Make it semi-bold with fontWeight w600
- 43.
- 44. 8px gap between title and price
- 45.
- 46. Price text with titleLarge style
- 47. Green color for the price
- 48. Bold weight for emphasis
- 49.
- 50. 12px gap before the button
- 51.
- 52. SizedBox with infinite width makes button full-width
- 53. ElevatedButton for the action
- 54. Label text
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
Spot the bug
Container(
color: Colors.white,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
),
child: Text('Hello'),
)Need a hint?
Show answer
Explain like I'm 5
Fun fact
Hands-on challenge
More resources
- Container Class (Flutter API)
- BoxDecoration Class (Flutter API)
- Understanding Constraints (Flutter Official)