Popular Searches
Popular Course Categories
Popular Courses

Flutter Cards and Material Design

Flutter Cards and Material Design

Flutter UI Components

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

  1. What is the Card widget in Flutter?
  2. What is Material Design?
  3. What is the purpose of a Card?
  4. Can a Card contain multiple widgets?
  5. How do you add padding inside a Card?
  6. How do you change Card elevation?
  7. How do you change the Card's background color?
  8. How do you create rounded corners on a Card?
  9. What is the purpose of clipBehavior?
  10. How can you make a Card clickable?
  11. What is the purpose of InkWell inside a Card?
  12. What are Card.filled and Card.outlined?
  13. What is CardThemeData?
  14. How can you apply a common Card style to an entire application?
  15. What is the difference between Card and Container?
  16. What is Material 3?
  17. How does elevation affect a Card?
  18. How can Cards be used in a GridView?
  19. How can Cards be used in a ListView?
  20. How do you create a responsive Card layout?

35. Practice Exercises

  1. Create a simple Card containing a title and description.
  2. Create a product Card with image, product name, price, and Buy Now button.
  3. Create a profile Card with avatar, name, profession, and action button.
  4. Create a course Card with course image, title, description, and Enroll button.
  5. Create three dashboard statistic Cards for Users, Orders, and Revenue.
  6. Create a clickable Card using InkWell.
  7. Create elevated, filled, and outlined Material 3 Cards.
  8. Create a Card containing a ListTile.
  9. Create a responsive GridView containing multiple Cards.
  10. Create a global CardThemeData for an application.
  11. Create a Card with custom border and rounded corners.
  12. 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

whatsapp