DEV Community

Cover image for Learning Flexbox Details by Building a Button in React Native
Vladimir Vovk
Vladimir Vovk

Posted on • Edited on

Learning Flexbox Details by Building a Button in React Native

Imaging we need to build a simple UI for an article preview. Something like this one:

Article preview design

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>
  )
}


Enter fullscreen mode Exit fullscreen mode

Pretty simple, right?

Button component

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.

Flex doc

flex will 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?

Flex direction doc

flexDirection controls 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 (flexDirection is default to column).

The main and cross axises

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?

Align items doc

alignItems describes how to align children along the cross axis of their container. It is very similar to justifyContent but instead of applying to the main axis, alignItems applies to the cross axis (alignItems is default to stretch).

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>
  );
}


Enter fullscreen mode Exit fullscreen mode

Learn more button

Looks good! 😻

But can we do it better without the "extra" View component? The answer is yes, we can! 💪

Align self doc

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>
  );
};


Enter fullscreen mode Exit fullscreen mode

Learn more button

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)