Material 3 Cards
Overview
Cards display content and actions about a single subject.
Material 3 Cards, using MaterialCardView
, come in three variants (Outlined, Filled, Elevated) with support for checkable and draggable states. They are ideal for presenting articles, products, or other focused content in lists or grids, adhering to Material Design guidelines. This guide covers implementation, accessibility, and theming.
Getting Started
- Add Material Components for Android library dependency
- Use
MaterialCardView
with Theme.Material3.*
for styling
- Apply styles for Outlined, Filled, or Elevated cards
- Ensure 8dp margins for mobile layouts
Accessibility
- Set
android:contentDescription
on content (e.g., images, buttons)
- Use
AccessibilityDelegate
for draggable cards with TalkBack
- Ensure checkable cards have clear interaction feedback
Behavior and States
- Default: Unchecked and not dragged
- Checked: Shows checked icon, changes foreground color
- Dragged: Applies foreground and elevation changes
- Use
setChecked
for checking, setDragged
for dragging
val card = findViewById<MaterialCardView>(R.id.card)
card.setOnLongClickListener {
card.isChecked = !card.isChecked
true
}
card.setOnClickListener {
// Handle card click
}
Card Variants
- Outlined Card: Minimal, stroked border for neutral display
- Filled Card: Solid background for moderate emphasis
- Elevated Card: Shadowed for high prominence
Outlined Card
- Minimal look with stroked border
- Ideal for lists or grids
Example
<com.google.android.material.card.MaterialCardView
android:id="@+id/card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
style="?attr/materialCardViewOutlinedStyle">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="194dp"
app:srcCompat="@drawable/media"
android:scaleType="centerCrop"
android:contentDescription="@string/content_description_media"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title"
android:textAppearance="?attr/textAppearanceTitleMedium"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/secondary_text"
android:textAppearance="?attr/textAppearanceBodyMedium"
android:textColor="?android:attr/textColorSecondary"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/supporting_text"
android:textAppearance="?attr/textAppearanceBodyMedium"
android:textColor="?android:attr/textColorSecondary"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:text="@string/action_1"
style="?attr/borderlessButtonStyle"/>
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/action_2"
style="?attr/borderlessButtonStyle"/>
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
val card = findViewById<MaterialCardView>(R.id.card)
card.setOnClickListener {
// Handle card click
}
Outlined Card Anatomy
Component |
Description |
Default State |
Checked State |
Dragged State |
Container |
1dp stroke, 0dp elevation |
colorSurface, colorOutline stroke |
colorSecondary stroke |
8dp elevation, light overlay |
Headline |
Optional title text |
Visible if set |
Visible if set |
Visible if set |
Subhead |
Optional secondary text |
Visible if set |
Visible if set |
Visible if set |
Supporting Text |
Optional descriptive text |
Visible if set |
Visible if set |
Visible if set |
Image |
Optional media, 194dp height |
Visible if set |
Visible if set |
Visible if set |
Buttons |
Optional action buttons |
Visible if set |
Visible if set |
Visible if set |
Checked Icon |
24dp, top-end, optional |
Hidden |
Visible, colorSecondary |
Hidden |
Filled Card
- Solid background for moderate emphasis
- Suitable for highlighted content
Example
<com.google.android.material.card.MaterialCardView
android:id="@+id/card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
style="?attr/materialCardViewFilledStyle">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="194dp"
app:srcCompat="@drawable/media"
android:scaleType="centerCrop"
android:contentDescription="@string/content_description_media"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title"
android:textAppearance="?attr/textAppearanceTitleMedium"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/secondary_text"
android:textAppearance="?attr/textAppearanceBodyMedium"
android:textColor="?android:attr/textColorSecondary"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:text="@string/action_1"
style="?attr/borderlessButtonStyle"/>
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/action_2"
style="?attr/borderlessButtonStyle"/>
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
val card = findViewById<MaterialCardView>(R.id.card)
card.setOnClickListener {
// Handle card click
}
Filled Card Anatomy
Component |
Description |
Default State |
Checked State |
Dragged State |
Container |
Solid background, 0dp elevation |
colorSurfaceContainerHighest |
Light overlay |
8dp elevation, light overlay |
Headline |
Optional title text |
Visible if set |
Visible if set |
Visible if set |
Subhead |
Optional secondary text |
Visible if set |
Visible if set |
Visible if set |
Supporting Text |
Optional descriptive text |
Visible if set |
Visible if set |
Visible if set |
Image |
Optional media, 194dp height |
Visible if set |
Visible if set |
Visible if set |
Buttons |
Optional action buttons |
Visible if set |
Visible if set |
Visible if set |
Checked Icon |
24dp, top-end, optional |
Hidden |
Visible, colorSecondary |
Hidden |
Elevated Card
- Shadowed for high prominence
- Ideal for featured content
Example
<com.google.android.material.card.MaterialCardView
android:id="@+id/card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
style="?attr/materialCardViewElevatedStyle">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="194dp"
app:srcCompat="@drawable/media"
android:scaleType="centerCrop"
android:contentDescription="@string/content_description_media"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title"
android:textAppearance="?attr/textAppearanceTitleMedium"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/secondary_text"
android:textAppearance="?attr/textAppearanceBodyMedium"
android:textColor="?android:attr/textColorSecondary"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:text="@string/action_1"
style="?attr/borderlessButtonStyle"/>
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/action_2"
style="?attr/borderlessButtonStyle"/>
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
val card = findViewById<MaterialCardView>(R.id.card)
card.setOnClickListener {
// Handle card click
}
Elevated Card Anatomy
Component |
Description |
Default State |
Checked State |
Dragged State |
Container |
Shadowed, 1dp elevation |
colorSurfaceContainerLow |
Light overlay |
2dp elevation, light overlay |
Headline |
Optional title text |
Visible if set |
Visible if set |
Visible if set |
Subhead |
Optional secondary text |
Visible if set |
Visible if set |
Visible if set |
Supporting Text |
Optional descriptive text |
Visible if set |
Visible if set |
Visible if set |
Image |
Optional media, 194dp height |
Visible if set |
Visible if set |
Visible if set |
Buttons |
Optional action buttons |
Visible if set |
Visible if set |
Visible if set |
Checked Icon |
24dp, top-end, optional |
Hidden |
Visible, colorSecondary |
Hidden |
Checkable Card
- Shows checked icon and foreground color change
- Enable with
android:checkable="true"
<com.google.android.material.card.MaterialCardView
android:id="@+id/card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:checkable="true"
style="?attr/materialCardViewOutlinedStyle">
<!-- Card content -->
</com.google.android.material.card.MaterialCardView>
val card = findViewById<MaterialCardView>(R.id.card)
card.setOnLongClickListener {
card.isChecked = !card.isChecked
true
}
Draggable Card
- Applies elevation and foreground overlay when dragged
- Use
ViewDragHelper
or DraggableCoordinatorLayout
<io.material.catalog.draggable.DraggableCoordinatorLayout
android:id="@+id/parentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.card.MaterialCardView
android:id="@+id/card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?attr/materialCardViewOutlinedStyle">
<!-- Card content -->
</com.google.android.material.card.MaterialCardView>
</io.material.catalog.draggable.DraggableCoordinatorLayout>
val parentContainer = findViewById<DraggableCoordinatorLayout>(R.id.parentContainer)
val card = findViewById<MaterialCardView>(R.id.card)
parentContainer.addDraggableChild(card)
parentContainer.setViewDragListener(object : DraggableCoordinatorLayout.ViewDragListener {
override fun onViewCaptured(view: View, pointerId: Int) {
card.isDragged = true
}
override fun onViewReleased(view: View, vX: Float, vY: Float) {
card.isDragged = false
}
})
Attributes and Usage
Element |
Attribute |
Related Method(s) |
Default Value |
Usage Description |
Variant |
Container |
app:cardBackgroundColor |
setCardBackgroundColor , getCardBackgroundColor |
Varies by style |
Sets background color |
All |
Container |
app:cardForegroundColor |
setCardForegroundColor , getCardForegroundColor |
Transparent |
Sets foreground overlay |
All |
Container |
app:strokeColor |
setStrokeColor , getStrokeColor |
colorOutline (unchecked), colorSecondary (checked) |
Sets stroke color |
Outlined |
Container |
app:strokeWidth |
setStrokeWidth , getStrokeWidth |
1dp (Outlined), 0dp (others) |
Sets stroke width |
Outlined |
Container |
app:shapeAppearance |
setShapeAppearanceModel , getShapeAppearanceModel |
shapeAppearanceCornerMedium |
Sets corner shape |
All |
Container |
app:cardElevation |
setCardElevation , getCardMaxElevation |
0dp (Outlined, Filled), 1dp (Elevated) |
Sets elevation |
All |
Checked Icon |
app:checkedIcon |
setCheckedIcon , getCheckedIcon |
ic_mtrl_checked_circle |
Sets checked icon |
All |
Checked Icon |
app:checkedIconTint |
setCheckedIconTint , getCheckedIconTint |
colorOutline (unchecked), colorSecondary (checked) |
Sets checked icon color |
All |
Theming Cards
- Customize color, typography, and shape
- Use
res/values/styles.xml
for theming
- Use
ShapeableImageView
for shaped media
Example
<style name="Theme.App" parent="Theme.Material3.*">
<item name="colorSecondary">@color/shrine_pink_100</item>
<item name="colorSurface">@color/shrine_pink_light</item>
</style>
<style name="Theme.App" parent="Theme.Material3.*">
<item name="materialCardViewStyle">@style/Widget.App.Card</item>
</style>
<style name="Widget.App.Card" parent="Widget.Material3.CardView.Elevated">
<item name="materialThemeOverlay">@style/ThemeOverlay.App.Card</item>
<item name="shapeAppearance">@style/ShapeAppearance.App.Card</item>
</style>
<style name="ThemeOverlay.App.Card" parent="">
<item name="colorSecondary">@color/shrine_pink_100</item>
<item name="colorSurface">@color/shrine_pink_light</item>
</style>
<style name="ShapeAppearance.App.Card" parent="">
<item name="cornerFamily">cut</item>
<item name="cornerSize">8dp</item>
</style>
<com.google.android.material.card.MaterialCardView
android:id="@+id/card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
style="?attr/materialCardViewElevatedStyle"
app:cardPreventCornerOverlap="false">
<com.google.android.material.imageview.ShapeableImageView
android:layout_width="match_parent"
android:layout_height="194dp"
app:srcCompat="@drawable/media"
android:scaleType="centerCrop"
android:contentDescription="@string/content_description_media"
app:shapeAppearance="?attr/shapeAppearanceCornerMedium"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.Card.Media"/>
<!-- Other card content -->
</com.google.android.material.card.MaterialCardView>
<style name="ShapeAppearanceOverlay.App.Card.Media" parent="">
<item name="cornerSizeBottomLeft">0dp</item>
<item name="cornerSizeBottomRight">0dp</item>
</style>
Material Design Documentation
- Adheres to Material Design guidelines for Cards
- Covers design, behavior, theming specifications
- Includes structure, accessibility, checkable/draggable states
- Refer to Material Design documentation for full details
FAQ
What are Material 3 Cards?
- Containers for content and actions about a single subject
How many card variants are there?
- Three variants: Outlined, Filled, Elevated
When to use an Elevated Card?
- Use for high-emphasis content needing prominence
How to make cards accessible?
- Set
contentDescription
on content; use AccessibilityDelegate
for draggable cards
Can I customize card appearance?
- Yes, theme via
res/values/styles.xml
How to add the Material 3 library?
- Include Material Components for Android library
Are there updates for the latest standards?
- Reflects latest Material 3 standards for cards