Overview
Image is a widget that displays an image.
The Image widget loads and displays images from network, local files, or assets. It supports various image formats and provides sizing and positioning options. You can control how the image fits into the allocated space using the objectFit property.
When to use it?
- When displaying images in your app
- When showing thumbnails or profile pictures
- When displaying background images or illustrations
- When actual images are needed instead of icons
- When responsive image layouts are required
Basic Usage
// Basic image
Image({
src: 'https://example.com/image.jpg'
})
// Image with specified size
Image({
src: '/assets/profile.png',
width: 100,
height: 100
})
// Image with fit options
Image({
src: '/assets/banner.jpg',
width: 300,
height: 200,
objectFit: 'cover',
objectPosition: 'center'
})
Props
src (required)
Value: string
The URL or path of the image to display.
Image({
src: 'https://example.com/photo.jpg' // Network image
})
Image({
src: '/images/logo.png' // Local image
})
width
Value: number | undefined
The width of the image in pixels.
Image({
src: '/image.jpg',
width: 200
})
height
Value: number | undefined
The height of the image in pixels.
Image({
src: '/image.jpg',
height: 150
})
objectFit
Value: ObjectFit | undefined
Determines how the image should be resized to fit the specified dimensions.
Available values:
'fill'
: Stretches the image to fill the entire area (default)'contain'
: Maintains aspect ratio and fits within the area'cover'
: Maintains aspect ratio and covers the entire area'none'
: Maintains original size'scale-down'
: Chooses the smaller of none or contain
Image({
src: '/banner.jpg',
width: 300,
height: 200,
objectFit: 'cover' // Maintain ratio and fill area
})
objectPosition
Value: ObjectPosition | undefined
Specifies the position of the image.
Available values:
'center'
: Center (default)'top'
: Top'right'
: Right'bottom'
: Bottom'left'
: Left'top left'
: Top left'top right'
: Top right'bottom left'
: Bottom left'bottom right'
: Bottom right
Image({
src: '/photo.jpg',
width: 200,
height: 200,
objectFit: 'cover',
objectPosition: 'top' // Show top portion
})
Practical Examples
Example 1: Profile Image
const ProfileImage = ({ imageUrl, name, size = 80 }) => {
return Container({
width: size,
height: size,
decoration: BoxDecoration({
borderRadius: BorderRadius.circular(size / 2),
border: Border.all({ color: '#E0E0E0', width: 2 })
}),
clipped: true,
child: imageUrl ?
Image({
src: imageUrl,
width: size,
height: size,
objectFit: 'cover',
objectPosition: 'center'
}) :
Container({
color: '#F0F0F0',
child: Center({
child: Text(name.charAt(0).toUpperCase(), {
style: TextStyle({
fontSize: size / 2,
fontWeight: 'bold',
color: '#666'
})
})
})
})
});
};
Example 2: Product Card
const ProductCard = ({ product }) => {
return Container({
decoration: BoxDecoration({
color: 'white',
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow({
color: 'rgba(0, 0, 0, 0.1)',
blurRadius: 8,
offset: { x: 0, y: 2 }
})
]
}),
clipped: true,
child: Column({
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
AspectRatio({
aspectRatio: 4 / 3,
child: Image({
src: product.imageUrl,
objectFit: 'cover'
})
}),
Padding({
padding: EdgeInsets.all(16),
child: Column({
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(product.name, {
style: TextStyle({
fontSize: 18,
fontWeight: 'bold'
})
}),
SizedBox({ height: 8 }),
Text(`$${product.price.toFixed(2)}`, {
style: TextStyle({
fontSize: 20,
color: '#FF5733',
fontWeight: 'bold'
})
})
]
})
})
]
})
});
};
Example 3: Image Gallery Item
const GalleryItem = ({ imageUrl, title, onTap }) => {
const [isHovered, setIsHovered] = useState(false);
return GestureDetector({
onTap: onTap,
onMouseEnter: () => setIsHovered(true),
onMouseLeave: () => setIsHovered(false),
child: Container({
decoration: BoxDecoration({
borderRadius: BorderRadius.circular(8),
boxShadow: isHovered ? [
BoxShadow({
color: 'rgba(0, 0, 0, 0.2)',
blurRadius: 12,
offset: { x: 0, y: 6 }
})
] : []
}),
clipped: true,
child: Stack({
children: [
Image({
src: imageUrl,
width: 300,
height: 200,
objectFit: 'cover'
}),
if (isHovered) Positioned({
bottom: 0,
left: 0,
right: 0,
child: Container({
padding: EdgeInsets.all(12),
decoration: BoxDecoration({
gradient: LinearGradient({
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: ['rgba(0, 0, 0, 0)', 'rgba(0, 0, 0, 0.7)']
})
}),
child: Text(title, {
style: TextStyle({
color: 'white',
fontSize: 16,
fontWeight: 'bold'
})
})
})
})
]
})
})
});
};
Example 4: Hero Header with Background
const HeroHeader = ({ backgroundImage, title, subtitle }) => {
return Container({
height: 400,
child: Stack({
fit: StackFit.expand,
children: [
Image({
src: backgroundImage,
objectFit: 'cover',
objectPosition: 'center'
}),
Container({
decoration: BoxDecoration({
gradient: LinearGradient({
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
'rgba(0, 0, 0, 0.3)',
'rgba(0, 0, 0, 0.7)'
]
})
})
}),
Center({
child: Column({
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(title, {
style: TextStyle({
fontSize: 48,
fontWeight: 'bold',
color: 'white'
})
}),
SizedBox({ height: 16 }),
Text(subtitle, {
style: TextStyle({
fontSize: 20,
color: 'rgba(255, 255, 255, 0.9)'
})
})
]
})
})
]
})
});
};
Example 5: Thumbnail List
const ThumbnailList = ({ images, selectedIndex, onSelect }) => {
return Container({
height: 80,
child: Row({
children: images.map((image, index) =>
GestureDetector({
onTap: () => onSelect(index),
child: Container({
width: 80,
height: 80,
margin: EdgeInsets.only({ right: 8 }),
decoration: BoxDecoration({
borderRadius: BorderRadius.circular(8),
border: Border.all({
color: index === selectedIndex ? '#2196F3' : '#E0E0E0',
width: index === selectedIndex ? 3 : 1
})
}),
clipped: true,
child: Opacity({
opacity: index === selectedIndex ? 1 : 0.7,
child: Image({
src: image.thumbnailUrl,
width: 80,
height: 80,
objectFit: 'cover'
})
})
})
})
)
})
});
};
Loading State Handling
The Image widget displays an empty space of the specified size while the image is loading. To show a loading indicator, separate state management is required:
const ImageWithLoader = ({ src, width, height }) => {
const [isLoading, setIsLoading] = useState(true);
return Stack({
children: [
Image({
src,
width,
height,
objectFit: 'cover'
}),
if (isLoading) Center({
child: CircularProgressIndicator()
})
]
});
};
Performance Considerations
- Image size: Use appropriately sized images for display
- Format selection: Consider efficient formats like WebP
- Lazy loading: Load only visible images in scroll areas
- Caching: Utilize browser caching
Important Notes
- If neither width nor height is specified, the original image size is used
- objectFit and objectPosition only take effect when image dimensions are specified
- Network images may be affected by CORS policies
- Some features may be limited in SVG rendering mode
Related Widgets
- Container: When additional styling is needed for images
- ClipRRect: To clip images with rounded corners
- AspectRatio: To maintain image aspect ratio
- FadeInImage: When fade-in effect is needed