Container & Decoration
The Container Widget
The Container widget is one of the most versatile and frequently used widgets in Flutter. It combines common painting, positioning, and sizing capabilities into a single convenient widget. A Container can apply padding, margins, borders, background colors, gradients, shadows, and transforms to its child.
Think of Container as a div in HTML/CSS -- it is the general-purpose box you use to style and position content.
Basic Container
Container(
width: 200,
height: 100,
color: Colors.blue,
child: const Center(
child: Text(
'Hello Container',
style: TextStyle(color: Colors.white),
),
),
)
Key Container properties:
width/height-- Fixed dimensions for the container.color-- Background color (cannot be used withdecoration).padding-- Space inside the container, between the border and the child.margin-- Space outside the container, between the container and its parent.alignment-- How to align the child within the container.constraints-- Additional size constraints (min/max width and height).decoration-- ABoxDecorationfor advanced styling (replacescolor).transform-- A matrix transformation applied to the container.
color and decoration on the same Container. If you need a background color along with borders or other decoration, set the color inside the BoxDecoration instead.Padding vs Margin
Understanding the difference between padding and margin is crucial for layout:
- Padding -- Space inside the container, between the container’s boundary and its child.
- Margin -- Space outside the container, between the container and surrounding widgets.
Padding vs Margin
Container(
// Space outside (pushes away from parent/siblings)
margin: const EdgeInsets.all(20),
// Space inside (pushes child inward)
padding: const EdgeInsets.all(16),
color: Colors.blue[100],
child: const Text('I have margin and padding'),
)
// EdgeInsets options:
// EdgeInsets.all(8) - same on all sides
// EdgeInsets.symmetric(horizontal: 16, vertical: 8)
// EdgeInsets.only(left: 10, top: 20)
// EdgeInsets.fromLTRB(10, 20, 10, 20) - left, top, right, bottom
BoxDecoration Deep Dive
BoxDecoration is the powerhouse of Container styling. It provides fine-grained control over the container’s visual appearance including colors, gradients, borders, rounded corners, shadows, and background images.
BoxDecoration Properties Overview
Container(
width: 200,
height: 200,
decoration: BoxDecoration(
// Background color
color: Colors.white,
// Rounded corners
borderRadius: BorderRadius.circular(16),
// Border
border: Border.all(
color: Colors.blue,
width: 2,
),
// Shadow
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: const Center(
child: Text('Decorated Box'),
),
)
Gradient Backgrounds
BoxDecoration supports three types of gradients: LinearGradient, RadialGradient, and SweepGradient.
Gradient Types
// Linear Gradient
Container(
width: 300,
height: 150,
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Colors.purple, Colors.blue, Colors.cyan],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(12),
),
)
// Radial Gradient
Container(
width: 200,
height: 200,
decoration: BoxDecoration(
gradient: RadialGradient(
colors: [Colors.yellow, Colors.orange, Colors.red],
radius: 0.8,
),
shape: BoxShape.circle,
),
)
// Sweep Gradient
Container(
width: 200,
height: 200,
decoration: const BoxDecoration(
gradient: SweepGradient(
colors: [
Colors.red,
Colors.orange,
Colors.yellow,
Colors.green,
Colors.blue,
Colors.purple,
Colors.red,
],
),
shape: BoxShape.circle,
),
)
Border Styles
You can apply uniform borders or different borders on each side:
Border Examples
// Uniform border
Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.blue, width: 2),
borderRadius: BorderRadius.circular(8),
),
)
// Different borders per side
Container(
decoration: const BoxDecoration(
border: Border(
top: BorderSide(color: Colors.red, width: 3),
bottom: BorderSide(color: Colors.blue, width: 3),
left: BorderSide(color: Colors.green, width: 1),
right: BorderSide(color: Colors.green, width: 1),
),
),
)
// Only bottom border (like an underline)
Container(
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(color: Colors.grey, width: 1),
),
),
)
Border() constructor), you cannot use borderRadius. Rounded corners only work with uniform borders created by Border.all().Box Shadows
The boxShadow property accepts a list of BoxShadow objects, allowing multiple shadows for complex effects:
Shadow Examples
// Single subtle shadow
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
)
// Multiple shadows for depth
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 20,
offset: const Offset(0, 10),
),
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 6,
offset: const Offset(0, 3),
),
],
),
)
Shape: Circle vs Rectangle
The shape property can be BoxShape.rectangle (default) or BoxShape.circle:
Circular Container
// Circular avatar-style container
Container(
width: 100,
height: 100,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.blue,
border: Border.all(color: Colors.white, width: 3),
boxShadow: [
BoxShadow(
color: Colors.blue.withOpacity(0.3),
blurRadius: 12,
offset: const Offset(0, 4),
),
],
),
child: const Center(
child: Text(
'AB',
style: TextStyle(
color: Colors.white,
fontSize: 32,
fontWeight: FontWeight.bold,
),
),
),
)
BoxShape.circle, do not set borderRadius -- it will throw an error. The circle shape automatically clips the container to a circle. Also ensure the Container has equal width and height for a perfect circle.Background Image
The image property of BoxDecoration allows you to set a background image:
Container with Background Image
Container(
width: 300,
height: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
image: const DecorationImage(
image: NetworkImage('https://picsum.photos/300/200'),
fit: BoxFit.cover,
),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.3),
blurRadius: 10,
offset: const Offset(0, 5),
),
],
),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
gradient: LinearGradient(
colors: [
Colors.black.withOpacity(0.6),
Colors.transparent,
],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
),
),
padding: const EdgeInsets.all(16),
alignment: Alignment.bottomLeft,
child: const Text(
'Image with Overlay',
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
)
Container Constraints
The constraints property accepts a BoxConstraints object that sets minimum and maximum dimensions:
Using Constraints
Container(
constraints: const BoxConstraints(
minWidth: 100,
maxWidth: 300,
minHeight: 50,
maxHeight: 200,
),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.teal[50],
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.teal),
),
child: const Text(
'This container adapts its size based on content, '
'but stays within the specified constraints.',
),
)
Container Transform
The transform property applies a Matrix4 transformation to the container. This is useful for rotations, scaling, and translations.
Transform Examples
// Rotation
Container(
width: 100,
height: 100,
transform: Matrix4.rotationZ(0.1), // radians
decoration: BoxDecoration(
color: Colors.orange,
borderRadius: BorderRadius.circular(12),
),
child: const Center(child: Text('Tilted')),
)
// Scale
Container(
width: 100,
height: 100,
transform: Matrix4.diagonal3Values(1.2, 1.2, 1),
transformAlignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.purple,
borderRadius: BorderRadius.circular(12),
),
child: const Center(
child: Text('Scaled', style: TextStyle(color: Colors.white)),
),
)
transformAlignment (available in Flutter 3.x) to set the origin point of the transformation. By default, transforms are applied from the top-left corner, which can produce unexpected results for rotations.DecoratedBox Widget
If you only need decoration without sizing or padding, use DecoratedBox directly instead of Container. It is a lighter widget that only applies a BoxDecoration:
DecoratedBox vs Container
// DecoratedBox - lightweight, decoration only
const DecoratedBox(
decoration: BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.all(Radius.circular(8)),
),
child: Padding(
padding: EdgeInsets.all(16),
child: Text('Using DecoratedBox'),
),
)
// Container does the same but with more overhead
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.circular(8),
),
child: const Text('Using Container'),
)
Practical Examples
Styled Card
Custom Styled Card
Container(
margin: const EdgeInsets.all(16),
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.08),
blurRadius: 16,
offset: const Offset(0, 4),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
Container(
width: 48,
height: 48,
decoration: BoxDecoration(
color: Colors.blue[50],
borderRadius: BorderRadius.circular(12),
),
child: Icon(Icons.star, color: Colors.blue[600]),
),
const SizedBox(width: 12),
const Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Premium Plan',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
Text(
'\$9.99/month',
style: TextStyle(color: Colors.grey),
),
],
),
],
),
const SizedBox(height: 16),
const Text(
'Unlock all features and get unlimited access.',
),
],
),
)
Circular Avatar
Custom Circular Avatar
Container(
width: 120,
height: 120,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: const LinearGradient(
colors: [Colors.purple, Colors.deepOrange],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
border: Border.all(color: Colors.white, width: 4),
boxShadow: [
BoxShadow(
color: Colors.purple.withOpacity(0.4),
blurRadius: 20,
offset: const Offset(0, 8),
),
],
),
child: const Center(
child: Text(
'ES',
style: TextStyle(
color: Colors.white,
fontSize: 40,
fontWeight: FontWeight.bold,
),
),
),
)
Practice Exercise
Create a profile card using Container and BoxDecoration that includes: (1) A gradient background from top-left to bottom-right. (2) Rounded corners with a radius of 20. (3) A subtle shadow with blur radius 15 and vertical offset 6. (4) Inside: a circular avatar Container at the top, a name Text, and a description Text. (5) The avatar should have a white border and a circular gradient. Challenge: Add a transform to slightly tilt the card and use DecorationImage for a background pattern.