This content originally appeared on Level Up Coding – Medium and was authored by Vamsi Vaddavalli
Understanding Compose’s Shadow Modifier System

Introduction
The Jetpack Compose framework now offers three distinct shadow modifiers, each designed for specific use cases and visual effects.
Complete Demo Project — Interactive examples of all shadow techniques covered in this article.
Basic Shadow (Modifier.shadow())
The traditional shadow() modifier follows Material Design principles and creates elevation-based shadows. This modifier simulates light from above and automatically clips shadows to match your composable's shape.
Card(
modifier = Modifier.shadow(
elevation = 8.dp,
shape = RoundedCornerShape(16.dp)
)
) {
Text("Material Design shadow")
}
Best for: Material Design compliance and simple elevation effects.
Drop Shadow (Modifier.dropShadow())
The dropShadow() modifier provides precise control over shadow appearance. You can customize radius, color, offset, and spread to achieve specific design requirements.
Box(
modifier = Modifier.dropShadow(
shape = RoundedCornerShape(12.dp),
shadow = Shadow(
radius = 8.dp,
color = Color.Black.copy(alpha = 0.2f),
offset = Offset(0f, 4f)
)
)
) {
Text("Custom drop shadow")
}
Best for: Custom designs that require precise shadow effects.
Inner Shadow (Modifier.innerShadow())
Inner shadows create depth by rendering shadows inside element borders, making components appear recessed or pressed into the surface.
Surface(
modifier = Modifier.innerShadow(
shape = CircleShape,
shadow = Shadow(
radius = 6.dp,
color = Color.Gray.copy(alpha = 0.3f)
)
)
) {
Icon(Icons.Default.Favorite, contentDescription = null)
}
Best for: Creating pressed states, neumorphic designs, or inset effects.
Implementation Considerations
Modifier Order Matters
When combining multiple shadow modifiers, their order in the chain affects the final appearance. Shadows are applied in sequence, so plan your modifier chain carefully.
Performance Impact
Compose’s shadow rendering is optimized for performance, but consider these guidelines:
- Use simpler shadows for scrolling lists
- Combine similar shadows when possible
- Test on lower-end devices for complex shadow combinations
Design Guidelines
- Consistency: Establish shadow patterns across your app
- Accessibility: Ensure shadows don't interfere with content readability
- Context: Match shadow intensity to your app’s visual style
Use case
Creating Button press states
Button(
onClick = {},
modifier = if (isPressed) {
Modifier.innerShadow(
shape = RoundedCornerShape(8.dp),
shadow = Shadow(radius = 4.dp, color = Color.Black.copy(0.1f))
)
} else {
Modifier.dropShadow(
shape = RoundedCornerShape(8.dp),
shadow = Shadow(radius = 6.dp, color = Color.Black.copy(0.15f))
)
}
) {
Text("Interactive Button")
}
References
Advanced Shadow Effects in Jetpack Compose was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.
This content originally appeared on Level Up Coding – Medium and was authored by Vamsi Vaddavalli