Mastering React Native cards & shadows
TLDR; When lacking contentContainerStyle on your ScrollView, its content might be a bit cut off.
Before starting to learn (and work, at the same time) with React Native, I was pretty confused about its styling system. Deep down, most of us still probably are. There are some very powerful libraries out there that give you beautiful and ready-to-use components (such as React Native Paper — a very powerful library, it gives you Material Design compliant components), but in this article I want to talk about designing a custom card component and the caveat that appears when using your cards in a ScrollView
.
Styling ScrollView’s content
On a recent project that I’ve worked on, we struggled a bit to understand why the shadows on our cards were not displayed properly throughout the app. It took some reading and debugging until I discovered this magic prop of ScrollView: contentContainerStyle
.
As it’s mentioned in its official documentation regarding this prop:
These styles will be applied to the scroll view content container which wraps all of the child views.
This is what this will look like:
<ScrollView contentContainerStyle={styles.scrollContainer}>{items}</ScrollView>
Your scrollContainer
style will look like this:
scrollContainer: {
paddingHorizontal: 2,
paddingVertical: 2,
}
Try using the ScrollContainer without passing a content style. Might work fine, but trust me that if you have some items which drop shadows, they’re not going to look that cool. In our case, the overall look of the app seemed unfinished, clumsy and didn’t really show off the great UX, look and feel that had been given to us by our designer. We were shocked to see how much difference some simple shadows could make.
What about the content of the ScrollView?
Glad you asked! I also want to share with you some code that might skip a visit to this shadow generator (which I totally recommend; it helps you with the trouble of writing correct and consistent shadows on both Android and iOS).
cardContainer: {
shadowColor: colors.SHADOW_COLOR,
shadowOpacity: 0.5,
shadowRadius: 5.0,
elevation: 3,
flex: 1,
alignItems: 'center',
horizontalPadding: 8,
verticalPadding: 8,
borderRadius: 10,
}
Small note: the padding values are hardcoded for the sake of the example. Please don’t hardcode values in real-world projects. Instead, extract them to your metrics file.
Your card component itself can easily be written from scratch.
export interface CustomCardProps extends ViewStyle {
children?: ReactNode;
style?: ViewStyle;
}
const Card = (props: CustomCardProps) => {
const { children, style, ...rest } = props;
return (
<View style={[styles.cardContainer, style]} {...rest}>
{children}
</View>);
};
export default Card;
There’s the most basic skeleton one could have for their custom card component. You will start adding more to it. Maybe wrap the View
in a TouchableOpacity
and providing an onPress
prop. The world is yours.
Thank you for reading the article! I hope I saved someone some time.
Do you have any interesting UI tips & tricks that took you way longer to discover than you would’ve liked?