Imaging we need to build a simple UI for an article preview. Something like this one:
Let's start building it from the bottom. Why not? π
We can use the Pressable and Text components to create the "Learn more" button.
import { Text, Pressable } from 'react-native'
type Props = {
children: string
}
export const Button = ({ children }: Props) => {
return (
<Pressable style={({pressed}) => ({
padding: 12,
borderWidth: 1,
borderRadius: 6,
backgroundColor: pressed ? 'lightyellow' : 'white',
})}>
<Text>{children}</Text>
</Pressable>
)
}
Pretty simple, right?
But wait, why the button is stretched full width? π€
We did not use the flex: 1, flexGrow: 1, or width: '100%' in our styles. π¬
Let's try to find the answer in the React Native Flexbox docs.
flexwill define how your items are going to βfillβ over the available space along your main axis.
Ok, flex controls only the "main" axis. But what is the "main" axis?
flexDirectioncontrols the direction in which the children of a node are laid out. This is also referred to as the main axis. The cross axis is the axis perpendicular to the main axis, or the axis which the wrapping lines are laid out in (flexDirectionis default tocolumn).
So, according to the docs the "main" axis for React Native by default is directed from top to bottom (which is different for the webβοΈ). It means, that in our case, flex and flexGrow styles do not affect the width of the button.
And what about the "cross" axis?
alignItemsdescribes how to align children along the cross axis of their container. It is very similar tojustifyContentbut instead of applying to the main axis,alignItemsapplies to the cross axis (alignItemsis default tostretch).
Eureka! That is it. As we can see now, for every element we add, the default behaviour for the "cross" axis will be stretch. That is why our button is stretched full width.
Let's try to fix it!
To do that, we need to change the "align" style for the "cross" axis, right? Theoretically, we can wrap the Pressible component with the View component and set the alignItems style for the wrapper View component to flex-start.
import { Text, Pressable, View } from 'react-native';
type Props = {
children: string;
};
export const Button = ({ children }: Props) => {
return (
<View style={{ alignItems: 'flex-start' }}>
<Pressable
style={({ pressed }) => ({
padding: 12,
borderWidth: 1,
borderRadius: 6,
backgroundColor: pressed ? 'lightyellow' : 'white',
})}>
<Text>{children}</Text>
</Pressable>
</View>
);
}
Looks good! π»
But can we do it better without the "extra" View component? The answer is yes, we can! πͺ
alignSelf has the same options and effect as alignItems but instead of affecting the children within a container, you can apply this property to a single child to change its alignment within its parent.
Wow, that is exactly what we need! π
We just need to apply the alignSelf: 'flex-start' style to the Pressible component. Let's try it.
import { Text, Pressable } from 'react-native';
type Props = {
children: string;
};
export const Button = ({ children }: Props) => {
return (
<Pressable
style={({ pressed }) => ({
padding: 12,
borderWidth: 1,
borderRadius: 6,
backgroundColor: pressed ? 'lightyellow' : 'white',
alignSelf: 'flex-start',
})}>
<Text>{children}</Text>
</Pressable>
);
};
Yey! It is what we wanted to achieve. π₯³
Awesome! I feel like we learned a lot just by building a simple button. That's amazing! π
Please, press the π button, if you like this article, and have a happy hacking! ππ»
P.S. You can play with the code using this Expo Snack.
Credits
Photo by kike vega on Unsplash
Image by Susann Mielke from Pixabay









Top comments (0)