The box model is how Flutter gives size, space, and style to visual elements.
So far, our apps have been functional but ugly. Black text on a white background. The time has come to make them beautiful.
If you come from web development, you’ll be used to having HTML (structure) on one side and CSS (style) on the other. That doesn’t exist in Flutter. Here, structure and style are fused together in the same Widget tree.
To design, we need to understand the Box Model. Everything in Flutter is a rectangular box, and today we are going to learn how to manipulate it with the most versatile widget of all: the Container.
The Container Widget
The Container is Flutter’s Swiss Army knife. It combines painting, positioning, and sizing of widgets. It is, essentially, a box that can have:
- Width and height (
width,height). - Background color.
- Borders and shadows.
- Margins and padding.
Container(
width: 200,
height: 100,
color: Colors.blue,
child: Text("I am a box"),
)Padding and Margin
This is the eternal doubt, but the distinction is simple if we look at the box:
Padding
It is the INTERNAL space. It is the distance between the edge of the box and its content (the child).
- Effect: It makes the box “fatter” or pushes the content inward.
- Example: The air inside a button so the text doesn’t touch the edges.
Margin
It is the EXTERNAL space. It is the distance between the box and its neighbors.
- Effect: It pushes other widgets away.
- Example: The space between two cards in a list.
Container(
margin: EdgeInsets.all(20), // Space OUTSIDE the blue box
padding: EdgeInsets.all(20), // Space INSIDE the box (around the text)
color: Colors.blue,
child: Text("Hello"),
)EdgeInsets to Control Spacing
For both margin and padding, Flutter uses the EdgeInsets class to define the values. We have several very useful constructors:
EdgeInsets.all(10): applies 10 logical pixels to all four sides.EdgeInsets.symmetric(horizontal: 20, vertical: 10): Very common in buttons. 20 on the sides, 10 on top and bottom.EdgeInsets.only(top: 15, left: 10): Only applies where you specify.EdgeInsets.fromLTRB(left, top, right, bottom): Full control (more verbose).
BoxDecoration to Style the Box
If you only want to put a background color, the color property of Container is enough. But if you want rounded corners, shadows, gradients, or background images, you need the decoration property.
This property receives a BoxDecoration object.
Container(
width: 300,
height: 150,
decoration: BoxDecoration(
color: Colors.white, // The background color goes INSIDE HERE
// Rounded corners
borderRadius: BorderRadius.circular(20),
// Line border
border: Border.all(
color: Colors.blueAccent,
width: 4,
),
// Shadows (List of shadows)
boxShadow: [
BoxShadow(
color: Colors.black26, // Color with transparency
blurRadius: 10, // How much it blurs
offset: Offset(5, 5), // Offset (X, Y)
)
],
),
child: Center(child: Text("Styled Box")),
)The Classic Color Mistake
Pay attention to this: the Container has a color property and a decoration property.
You cannot use color and decoration at the same time.
If you use decoration, the background color MUST go inside the BoxDecoration. If you leave it outside, Flutter will throw a runtime error (the famous red screen).
// ❌ WRONG: Will cause an error
Container(
color: Colors.red,
decoration: BoxDecoration(borderRadius: BorderRadius.circular(10)),
)
// ✅ CORRECT
Container(
decoration: BoxDecoration(
color: Colors.red, // The color moves here
borderRadius: BorderRadius.circular(10),
),
)Dimensions and Constraints
Finally, let’s talk about size.
widthandheight: Set a specific size in logical pixels.double.infinity: Tells the Container to try to occupy all the possible width (or height) allowed by its parent.
Container(
width: double.infinity, // Occupies the entire screen width
height: 100,
color: Colors.green,
)The size of a Container always depends on the constraints it receives from its parent. Without a child or its own size, it usually tries to occupy all the allowed space; with a child, it usually tries to fit itself to it, always within those constraints.
Specialized Widgets
Although the Container can do everything, sometimes it is more efficient and readable to use specific widgets if you only need one thing:
- Only need internal space? Use the
Paddingwidget. - Only need to center something? Use the
Centerwidget. - Only need to set a specific size? Use the
SizedBoxwidget.