Lesson 23 of 51 beginner

Container, Padding & SizedBox

Spacing, Sizing, and Decoration

Open interactive version (quiz + challenge)

Real-world analogy

Think of Container like a gift box — it has a specific size, padding inside (bubble wrap around the gift), margin outside (space between boxes on the shelf), and decoration (wrapping paper with patterns and color). Padding is just bubble wrap by itself, and SizedBox is an invisible spacer block you use to create exact gaps.

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

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. 1. Import the Material package
  2. 2.
  3. 3. Define ProductCard as a StatelessWidget
  4. 4. Declare required string fields for title, price, and image URL
  5. 5.
  6. 6.
  7. 7.
  8. 8.
  9. 9.
  10. 10.
  11. 11. Build method creates the widget tree
  12. 12.
  13. 13. Return a Container as the outer wrapper
  14. 14. Margin of 8px on all sides separates cards from each other
  15. 15. BoxDecoration defines the visual style
  16. 16. Use the theme's surface color for the background
  17. 17. 16px border radius for rounded corners
  18. 18. BoxShadow list for the drop shadow effect
  19. 19. Black at 8% opacity for a subtle shadow
  20. 20. 12px blur radius for soft edges
  21. 21. Offset 0 horizontal, 4 vertical for shadow below the card
  22. 22.
  23. 23.
  24. 24. Column stacks image and text content vertically
  25. 25. Left-align all children
  26. 26.
  27. 27. ClipRRect clips the image to match rounded top corners
  28. 28. Only round the top corners (top-left and top-right)
  29. 29.
  30. 30. Image.network loads the image from a URL
  31. 31. Fixed height of 180px
  32. 32. Width fills the container
  33. 33. BoxFit.cover scales and crops to fill the area
  34. 34.
  35. 35.
  36. 36. Padding wraps the text content section
  37. 37. 16px padding on all sides
  38. 38. Inner Column for text content
  39. 39. Left-align text
  40. 40.
  41. 41. Title text with titleMedium style
  42. 42. Make it semi-bold with fontWeight w600
  43. 43.
  44. 44. 8px gap between title and price
  45. 45.
  46. 46. Price text with titleLarge style
  47. 47. Green color for the price
  48. 48. Bold weight for emphasis
  49. 49.
  50. 50. 12px gap before the button
  51. 51.
  52. 52. SizedBox with infinite width makes button full-width
  53. 53. ElevatedButton for the action
  54. 54. Label text
  55. 55.
  56. 56.
  57. 57.
  58. 58.
  59. 59.
  60. 60.

Spot the bug

Container(
  color: Colors.white,
  decoration: BoxDecoration(
    borderRadius: BorderRadius.circular(12),
  ),
  child: Text('Hello'),
)
Need a hint?
Can Container have both color and decoration at the same time?
Show answer
You cannot use both the color property and decoration property on a Container. The color is a shorthand for decoration's color. Fix: remove the color property and add it inside BoxDecoration: decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(12))

Explain like I'm 5

Imagine you are mailing a present. The present is your widget. Padding is the bubble wrap you put INSIDE the box around the present. Margin is the space the mailman leaves between your box and other boxes on the truck. Container is the whole shipping box — it has a size, padding inside, and you can decorate it with wrapping paper (BoxDecoration). SizedBox is just an empty block you put between boxes to keep them apart.

Fun fact

Container is actually a convenience widget that combines up to 7 different widgets internally: Align, Padding, DecoratedBox, ConstrainedBox, Transform, ClipPath, and LimitedBox. When you only need one of these features, using the specific widget is more efficient!

Hands-on challenge

Build a product card with these layers: an outer Container with 8px margin, rounded corners, and a subtle shadow. Inside, an image at the top clipped to match the rounded corners. Below the image, a Padding of 16px wrapping a Column with a title, an 8px SizedBox, a price in green, a 12px SizedBox, and a full-width ElevatedButton.

More resources

Open interactive version (quiz + challenge) ← Back to course: Flutter & Dart