Flexbox Exercise: Building a Card Game Board
Tags: reactnative
Published: 2022-07-11 16:51:40

---
title: "Flexbox Exercise: Building a Card Game Board"
published: true
description: A quick exercise (under 3 minutes) to practice using Flexbox to build layouts in React Native.
tags: reactnative
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c69v0gk1hgn4xdmm0uhg.png
# Use a ratio of 100:42 for best results.
canonical_url: https://www.reactnativeschool.com/flexbox-exercise-building-a-card-game-board
---

In a recent [open source React Native app](https://github.com/ReactNativeSchool/match-the-pairs-react-native) I had to build a grid of cards to fill the screen. After having a handful of conversations regarding Flexbox recently I thought this would be a nice quick exercise to get some practice.

The app is based on the following reference. All we'll be doing today is the grid layout. The rest (animations, custom hooks, etc.) will be covered later.

![Card game on iOS, Android, and the Web](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c69v0gk1hgn4xdmm0uhg.png)


You can quickly do the exercise via [Expo Snack](https://snack.expo.dev/).

The requirements are:

- Equally fill the remainder of the screen with cards (after other UI elements like stats or buttons)
- Resize for changing screen sizes (such as on web)
- Automatically adjust layout based on number of cards in a row

[Flexbox](https://reactnative.dev/docs/flexbox) is the perfect tool for this in React Native. Though it can take some time to get used to, this is a good exercise to start getting more comfortable with it.

Our end goal, for this exercise, is the following:

![A grid with 3 rows of 3 cards](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q0xfl0gxwne2xw4150fh.PNG) 

Let's start with the following code.

```jsx
import * as React from "react"
import { Text, View, StyleSheet } from "react-native"
import Constants from "expo-constants"

const Card = () => <View style={styles.card} />

export default function App() {
  return (
    <View style={styles.container}>
      <Text>This is top filler</Text>
      <View style={styles.row}>
        <Card />
        <Card />
        <Card />
      </View>
      <View style={styles.row}>
        <Card />
        <Card />
        <Card />
      </View>
      <View style={styles.row}>
        <Card />
        <Card />
        <Card />
      </View>
      <Text>This is bottom filler</Text>
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    paddingTop: Constants.statusBarHeight,
  },
  row: {},
  card: {
    backgroundColor: "#7ca1b4",
  },
})
```

We want each of our rows to equally fill the vertical space and each of our cards to fill that row vertically and to evenly split the space horizontally.

First we want our container to fill up the entire screen. We can do this by setting `flex: 1` on our `container` styles. This is best visualized by temporarily setting a background color.

![Full screen green background](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/la2qhnl92h9s6yj8qdpl.PNG) 

```jsx
// ...

const styles = StyleSheet.create({
  container: {
    paddingTop: Constants.statusBarHeight,
    flex: 1,
    backgroundColor: "green",
  },
  row: {},
  card: {
    backgroundColor: "#7ca1b4",
  },
})
```

Now, we need to tell the `row` to evenly split the remainder of the screen (via `flex: 1`).

![A screen with 3 equal blue sections](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xwwrlohl92rm0osrgl4t.PNG)
 

```jsx
// ...

const styles = StyleSheet.create({
  container: {
    paddingTop: Constants.statusBarHeight,
    flex: 1,
    backgroundColor: "green",
  },
  row: {
    flex: 1,
    backgroundColor: "blue",
    marginVertical: 5,
  },
  card: {
    backgroundColor: "#7ca1b4",
  },
})
```

Because each row has a `flex: 1` on it the rendering engine knows that each row should take up 1/3 of the available space. If one row had `flex: 2` on it, then a `flex: 1` would take up 1/5 and a `flex: 2` would take up 2/5 of the area.

Next we want our cards to fill the remaining space, sharing it equally. Again we'll leverage `flex: 1`.

![Each row split into 3 cards, aligned vertically](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8a2xt8xxzvn86le0905v.PNG)
 

```jsx
// ...

const styles = StyleSheet.create({
  container: {
    paddingTop: Constants.statusBarHeight,
    flex: 1,
    backgroundColor: "green",
  },
  row: {
    flex: 1,
    backgroundColor: "blue",
    marginVertical: 5,
  },
  card: {
    backgroundColor: "#7ca1b4",
    flex: 1,
    margin: 5,
  },
})
```

Now, with this, the cards aren't rendered correctly. We want them rendered horizontally, but still split the space equally. We can accomplish this with `flexDirection: 'row'` on our `row` style. By default Flexbox in React Native sets the flex direction to column. We'll also remove our placeholder background colors.

![A grid with 3 rows of 3 cards](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oj57jx6v142cjvm6mv8k.PNG) 

```jsx
// ...

const styles = StyleSheet.create({
  container: {
    paddingTop: Constants.statusBarHeight,
    flex: 1,
  },
  row: {
    flex: 1,
    marginVertical: 5,
    flexDirection: "row",
  },
  card: {
    backgroundColor: "#7ca1b4",
    flex: 1,
    margin: 5,
  },
})
```

Since we're using flexbox to manage our layout we can be confident that it will fill the screen correctly no matter what size the screen is and that it will also automatically resize if the screen size changes.

![An example of how Flexbox updates the layout as screen size changes](https://media.giphy.com/media/5lLk41kGAeh33i11Ap/giphy.gif)


This was a super brief exercise into practicing layout with Flexbox. If you'd like to learn more I wrote a more [in depth article on Flexbox over on LogRocket](https://blog.logrocket.com/using-flexbox-react-native/).