Flutter Cards and Material Design
Flutter provides a powerful Material Design widget system for building modern, consistent, and responsive user interfaces. One of the most commonly used Material components is the Card widget. A Card is useful for grouping related information inside a visually separated surface with rounded corners and elevation.
Flutter's Material library implements Material Design components, and current Flutter versions use Material 3 as the default design language. The Card widget supports elevated, filled, and outlined variants when Material 3 is enabled. :contentReference[oaicite:0]{index=0}
1. What is Material Design?
Material Design is a design system created by Google for building consistent and user-friendly digital interfaces. Flutter provides many Material widgets that implement Material Design concepts such as cards, buttons, app bars, dialogs, navigation components, typography, colors, elevation, and surfaces.
Flutter's Material widgets are available through:
import 'package:flutter/material.dart';
Material Design helps developers create interfaces that have consistent:
- Colors
- Typography
- Spacing
- Shapes
- Elevation
- Buttons
- Cards
- Navigation
- Interaction behavior
- Accessibility patterns
2. What is a Card in Flutter?
A Card is a Material Design surface used to display related information in a visually grouped area. It normally has rounded corners and an elevation/shadow effect.
Cards can contain almost any Flutter widget, including:
- Text
- Images
- Icons
- Buttons
- ListTile
- Rows
- Columns
- Containers
- Forms
- Other cards or custom widgets
A Card has one direct child, but that child can be a Row, Column, ListView, or another widget that contains multiple children. :contentReference[oaicite:1]{index=1}
3. Basic Card Syntax
Card(
child: const Text('Hello Flutter'),
)
A more useful example is:
Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
const Text(
'Flutter Card',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
const Text(
'This is a simple Material Card.',
),
],
),
),
)
4. Why Use Cards?
Cards are useful when an application contains multiple independent pieces of related information.
Common examples include:
- Product cards
- Profile cards
- Course cards
- News cards
- Dashboard statistics
- Order information
- Payment information
- Contact information
- Event information
- Restaurant or food items
- Travel destinations
- Social media posts
5. Card with Padding
Padding creates internal spacing between the Card boundary and its content.
Card(
child: Padding(
padding: const EdgeInsets.all(20),
child: const Text(
'Welcome to Flutter',
),
),
)
You can also use different horizontal and vertical padding:
Card(
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 15,
),
child: const Text('Flutter Card'),
),
)
6. Card with Background Color
The color property controls the Card's background color.
Card(
color: Colors.blue,
child: const Padding(
padding: EdgeInsets.all(20),
child: Text(
'Blue Card',
style: TextStyle(
color: Colors.white,
),
),
),
)
For Material 3 designs, card appearance can also be influenced by theme and surface tint behavior.
7. Card Elevation
Elevation controls how visually elevated a Material surface appears above the surrounding surface. For a Card, elevation affects the shadow beneath it.
Card(
elevation: 8,
child: const Padding(
padding: EdgeInsets.all(20),
child: Text('Elevated Card'),
),
)
Higher elevation generally creates a more noticeable shadow.
Low Elevation
Card(
elevation: 2,
child: const Text('Low Elevation'),
)
High Elevation
Card(
elevation: 12,
child: const Text('High Elevation'),
)
Use elevation carefully. Excessive shadows can make an interface visually heavy.
8. Card Shape
The shape property allows you to customize the shape of a Card.
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: const Padding(
padding: EdgeInsets.all(20),
child: Text('Rounded Card'),
),
)
In Material 3, the default Card shape uses rounded corners, with the default corner radius determined by the Material 3 theme. :contentReference[oaicite:2]{index=2}
9. Card with Border
You can create a Card with a border by using an appropriate ShapeBorder.
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
side: const BorderSide(
color: Colors.blue,
width: 2,
),
),
child: const Padding(
padding: EdgeInsets.all(20),
child: Text('Bordered Card'),
),
)
10. Card Margin
The margin property controls the space outside the Card.
Card(
margin: const EdgeInsets.all(20),
child: const Padding(
padding: EdgeInsets.all(20),
child: Text('Card with Margin'),
),
)
Margin is useful when several cards are displayed vertically or horizontally.
11. Card with ListTile
ListTile is commonly used inside Cards because it provides a convenient structure for leading icons, titles, subtitles, and trailing widgets.
Card(
child: ListTile(
leading: const CircleAvatar(
child: Icon(Icons.person),
),
title: const Text('Manish'),
subtitle: const Text('Flutter Developer'),
trailing: const Icon(Icons.arrow_forward_ios),
),
)
This pattern is useful for:
- User profiles
- Settings
- Contacts
- Messages
- Notifications
- Menu items
12. Card with Image
Card(
clipBehavior: Clip.antiAlias,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.network(
'https://picsum.photos/600/300',
width: double.infinity,
height: 180,
fit: BoxFit.cover,
),
const Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Beautiful Destination',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 8),
Text(
'Explore amazing places with Flutter.',
),
],
),
),
],
),
)
13. Why clipBehavior is Useful
When a Card contains an image or another widget that should follow the Card's rounded shape, clipBehavior can be used.
Card(
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
child: Image.network(
'https://picsum.photos/600/300',
height: 200,
width: double.infinity,
fit: BoxFit.cover,
),
)
This clips the child according to the Card's shape.
14. Product Card Example
Card(
clipBehavior: Clip.antiAlias,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.network(
'https://picsum.photos/500/300',
height: 180,
width: double.infinity,
fit: BoxFit.cover,
),
const Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Wireless Headphones',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 8),
Text(
'₹2,999',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 12),
],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: Row(
children: [
Expanded(
child: OutlinedButton(
onPressed: () {},
child: const Text('Details'),
),
),
const SizedBox(width: 10),
Expanded(
child: ElevatedButton(
onPressed: () {},
child: const Text('Buy Now'),
),
),
],
),
),
],
),
)
15. Profile Card Example
Card(
child: Padding(
padding: const EdgeInsets.all(20),
child: Row(
children: [
const CircleAvatar(
radius: 35,
child: Icon(Icons.person),
),
const SizedBox(width: 15),
const Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'John Doe',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 5),
Text('Flutter Developer'),
Text('Mumbai, India'),
],
),
),
IconButton(
onPressed: () {},
icon: const Icon(Icons.more_vert),
),
],
),
),
)
16. Course Card Example
Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Icon(
Icons.flutter_dash,
size: 50,
),
const SizedBox(height: 12),
const Text(
'Flutter Development',
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
const Text(
'Learn Flutter and Dart from fundamentals to advanced application development.',
),
const SizedBox(height: 15),
ElevatedButton(
onPressed: () {},
child: const Text('Enroll Now'),
),
],
),
),
)
17. Dashboard Statistic Cards
Cards are commonly used to display dashboard statistics.
Row(
children: [
Expanded(
child: Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
const Icon(Icons.people),
const SizedBox(height: 8),
const Text(
'12,450',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
const Text('Users'),
],
),
),
),
),
Expanded(
child: Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
const Icon(Icons.shopping_cart),
const SizedBox(height: 8),
const Text(
'3,240',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
const Text('Orders'),
],
),
),
),
),
],
)
18. Making a Card Clickable
A Card can act as a large touch target. One common approach is to place an InkWell inside the Card.
Card(
child: InkWell(
onTap: () {
print('Card tapped');
},
child: const Padding(
padding: EdgeInsets.all(20),
child: Row(
children: [
Icon(Icons.article),
SizedBox(width: 15),
Text('Open Article'),
],
),
),
),
)
Using InkWell allows the card to respond to taps with Material interaction effects. Flutter's Card documentation also demonstrates using InkWell when the Card itself is the primary action area. :contentReference[oaicite:3]{index=3}
19. Clickable Card with Rounded Corners
Card(
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
child: InkWell(
onTap: () {
print('Course opened');
},
child: const Padding(
padding: EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Flutter Course',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 8),
Text('Tap to view course details.'),
],
),
),
),
)
20. Material 3 Card Variants
Material 3 provides three main Card variants in Flutter:
- Card: The default elevated card.
- Card.filled: A filled card variant.
- Card.outlined: An outlined card variant.
Flutter's API documentation specifies these variants for Material 3. In Material 2 mode, the named variants behave like the default elevated Card. :contentReference[oaicite:4]{index=4}
Elevated Card
Card(
child: const Padding(
padding: EdgeInsets.all(20),
child: Text('Elevated Card'),
),
)
Filled Card
Card.filled(
child: const Padding(
padding: EdgeInsets.all(20),
child: Text('Filled Card'),
),
)
Outlined Card
Card.outlined(
child: const Padding(
padding: EdgeInsets.all(20),
child: Text('Outlined Card'),
),
)
21. Material 3 Theme
Material 3 is the default design language in current Flutter versions. It can be explicitly enabled through ThemeData.
MaterialApp(
theme: ThemeData(
useMaterial3: true,
),
home: const HomePage(),
)
Material 3 became the default in Flutter 3.16. :contentReference[oaicite:5]{index=5}
22. CardTheme
CardTheme and CardThemeData can be used to provide common styling for Cards throughout an application. Theme-level properties can define values such as color, elevation, margin, shape, shadow color, surface tint, and clipping behavior. :contentReference[oaicite:6]{index=6}
MaterialApp(
theme: ThemeData(
useMaterial3: true,
cardTheme: const CardThemeData(
elevation: 3,
margin: EdgeInsets.all(10),
),
),
home: const HomePage(),
)
This makes it easier to maintain a consistent card design across the application.
23. Card with Custom Theme
MaterialApp(
theme: ThemeData(
useMaterial3: true,
cardTheme: CardThemeData(
color: Colors.white,
elevation: 3,
margin: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 8,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
),
),
home: const HomePage(),
)
24. Cards in a ListView
Cards are frequently used inside scrolling lists.
ListView(
padding: const EdgeInsets.all(16),
children: [
Card(
child: ListTile(
leading: const Icon(Icons.home),
title: const Text('Home'),
subtitle: const Text('Home address'),
),
),
Card(
child: ListTile(
leading: const Icon(Icons.work),
title: const Text('Work'),
subtitle: const Text('Office address'),
),
),
Card(
child: ListTile(
leading: const Icon(Icons.school),
title: const Text('Education'),
subtitle: const Text('College information'),
),
),
],
)
25. Cards in a GridView
Cards can also be used in a grid layout for products, courses, categories, and dashboards.
GridView.count(
crossAxisCount: 2,
padding: const EdgeInsets.all(16),
crossAxisSpacing: 10,
mainAxisSpacing: 10,
children: [
Card(
child: const Center(
child: Text('Flutter'),
),
),
Card(
child: const Center(
child: Text('Dart'),
),
),
Card(
child: const Center(
child: Text('Firebase'),
),
),
Card(
child: const Center(
child: Text('Android'),
),
),
],
)
26. Card with Multiple Sections
Card(
child: Column(
children: [
const ListTile(
leading: Icon(Icons.person),
title: Text('John Doe'),
subtitle: Text('Flutter Developer'),
),
const Divider(),
const Padding(
padding: EdgeInsets.all(16),
child: Text(
'John is working on a Flutter mobile application.',
),
),
Padding(
padding: const EdgeInsets.all(16),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () {},
child: const Text('View'),
),
ElevatedButton(
onPressed: () {},
child: const Text('Contact'),
),
],
),
),
],
),
)
27. Material Surface and Elevation
Material Design uses the concept of surfaces and elevation to communicate visual relationships between interface elements. Flutter's Material widget represents a piece of material and can provide elevation, shadows, shapes, clipping, and ink effects. Card is a specialized Material surface. :contentReference[oaicite:7]{index=7}
For example:
Material(
elevation: 4,
borderRadius: BorderRadius.circular(12),
child: const Padding(
padding: EdgeInsets.all(20),
child: Text('Material Surface'),
),
)
28. Card vs Container
| Feature |
Card |
Container |
| Material Design behavior |
Yes |
Not by itself |
| Elevation |
Built-in |
Requires decoration/shadow |
| Rounded shape |
Built-in Material shape |
Configured manually |
| Material surface |
Yes |
No |
| Common purpose |
Related content surface |
General-purpose layout/styling |
Use a Card when you need a Material surface representing related content. Use a Container when you mainly need layout, padding, alignment, or decoration.
29. Card vs Material Widget
A Card is essentially a convenient Material Design surface specialized for card-like content. The Material widget is more general and provides lower-level control over Material surfaces, elevation, shape, clipping, and ink effects. :contentReference[oaicite:8]{index=8}
Card(
child: const Text('Simple Card'),
)
Compared with:
Material(
elevation: 4,
borderRadius: BorderRadius.circular(12),
child: const Padding(
padding: EdgeInsets.all(20),
child: Text('Custom Material Surface'),
),
)
30. Complete Flutter Card Example
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
useMaterial3: true,
),
home: const CardDemo(),
);
}
}
class CardDemo extends StatelessWidget {
const CardDemo({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Cards'),
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
Card(
elevation: 4,
clipBehavior: Clip.antiAlias,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.network(
'https://picsum.photos/600/300',
width: double.infinity,
height: 200,
fit: BoxFit.cover,
),
const Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
'Flutter Development',
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 8),
Text(
'Learn Flutter and build modern mobile applications.',
),
],
),
),
Padding(
padding: const EdgeInsets.all(16),
child: Row(
mainAxisAlignment:
MainAxisAlignment.end,
children: [
OutlinedButton(
onPressed: () {},
child: const Text('Details'),
),
const SizedBox(width: 10),
ElevatedButton(
onPressed: () {},
child: const Text('Enroll'),
),
],
),
),
],
),
),
Card.filled(
child: const Padding(
padding: EdgeInsets.all(20),
child: Text(
'This is a Material 3 filled card.',
),
),
),
Card.outlined(
child: const Padding(
padding: EdgeInsets.all(20),
child: Text(
'This is a Material 3 outlined card.',
),
),
),
],
),
);
}
}
31. Responsive Card Layout
Cards should adapt to different screen sizes. For example, a mobile application may display one card per row while a tablet or desktop layout may display multiple cards.
LayoutBuilder(
builder: (context, constraints) {
int columns = constraints.maxWidth > 800
? 3
: constraints.maxWidth > 500
? 2
: 1;
return GridView.count(
crossAxisCount: columns,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
padding: const EdgeInsets.all(16),
children: [
Card(
child: const Center(
child: Text('Card 1'),
),
),
Card(
child: const Center(
child: Text('Card 2'),
),
),
Card(
child: const Center(
child: Text('Card 3'),
),
),
],
);
},
)
32. Card Design Best Practices
- Use Cards to group related information.
- Keep card content organized and easy to scan.
- Use consistent spacing between cards.
- Avoid excessive elevation and shadows.
- Use meaningful titles and descriptions.
- Use images with appropriate aspect ratios.
- Use buttons for clear actions.
- Use InkWell when the entire Card is intended to be tappable.
- Use consistent corner radii across related UI components.
- Use Material 3 components consistently throughout the application.
- Make card content responsive on different screen sizes.
- Avoid putting too much unrelated information into a single card.
33. Common Mistakes
Mistake 1: Too Much Content
A Card should group related information rather than becoming a complete page inside a small container.
Mistake 2: Excessive Shadows
Very high elevation values can make an interface look visually heavy. Use elevation purposefully.
Mistake 3: Inconsistent Card Sizes
Cards in the same section should generally follow a consistent visual structure.
Mistake 4: Poor Spacing
Always provide enough padding inside cards and spacing between adjacent cards.
Mistake 5: Making Cards Look Clickable Without Interaction
If a card visually appears interactive, provide an appropriate interaction such as InkWell or a clear action button.
34. Interview Questions
- What is the Card widget in Flutter?
- What is Material Design?
- What is the purpose of a Card?
- Can a Card contain multiple widgets?
- How do you add padding inside a Card?
- How do you change Card elevation?
- How do you change the Card's background color?
- How do you create rounded corners on a Card?
- What is the purpose of clipBehavior?
- How can you make a Card clickable?
- What is the purpose of InkWell inside a Card?
- What are Card.filled and Card.outlined?
- What is CardThemeData?
- How can you apply a common Card style to an entire application?
- What is the difference between Card and Container?
- What is Material 3?
- How does elevation affect a Card?
- How can Cards be used in a GridView?
- How can Cards be used in a ListView?
- How do you create a responsive Card layout?
35. Practice Exercises
- Create a simple Card containing a title and description.
- Create a product Card with image, product name, price, and Buy Now button.
- Create a profile Card with avatar, name, profession, and action button.
- Create a course Card with course image, title, description, and Enroll button.
- Create three dashboard statistic Cards for Users, Orders, and Revenue.
- Create a clickable Card using InkWell.
- Create elevated, filled, and outlined Material 3 Cards.
- Create a Card containing a ListTile.
- Create a responsive GridView containing multiple Cards.
- Create a global CardThemeData for an application.
- Create a Card with custom border and rounded corners.
- Create a Card with an image clipped to rounded corners.
36. Key Takeaways
- Card is a Material Design widget used to group related information.
- Cards commonly have rounded corners and elevation.
- Cards can contain almost any Flutter widget.
- elevation controls the Card's visual shadow/elevation.
- shape controls the Card's shape and border geometry.
- margin controls space outside the Card.
- clipBehavior can be used to clip child content to the Card's shape.
- Card.filled and Card.outlined provide Material 3 Card variants.
- InkWell can make a Card respond to taps with Material interaction feedback.
- CardThemeData can provide consistent styling for Cards throughout an application.
- Cards work well with ListView, GridView, Row, Column, ListTile, images, buttons, and other widgets.
- Material 3 is the default design language in current Flutter versions.
37. Learning Resources
Official Flutter Documentation