0

I have a parent view which width is "100%" (not screen width), and I want to have each children with the same width and height.

My codes is:

<View style={styles.container}>
  <View style={styles.item} />
  <View style={styles.item} />
  <View style={styles.item} />
  <View style={styles.item} />
</View>

const styles = StyleSheet.create({
  container: {
    width: "100%",
    flexDirection: "row",
    alignItems: "center",
  },
  item: {
    width: 75,
    height: 75,
    marginRight: 10,
    backgroundColor: "red",
  },
});

But this is not responsive for all devices (in small sevices some of the children go out of screen)... Is there any other way to do that?

Thank you.

Raul
  • 2,673
  • 1
  • 15
  • 52

2 Answers2

2
  container: {
    flexDirection: "row",
    alignItems: "center",
  },
  item: {
    flex: 1,
    aspectRatio: 1,
    backgroundColor: "red",
  },

The trick for your situation is aspectRatio. Just make each child flex: 1, but with an aspect ratio of 1 to make them squared.

Victor Molina
  • 2,353
  • 2
  • 19
  • 49
1

Percentage widths

There are likely many ways to do this, but the first one that comes to mind is setting the widths to percentages. This makes the item a percentage of the parent.

  item: {
    width: '30%',
    height: 75,
    marginRight: 10,
    backgroundColor: "red",
  }

If you need something more flexible, you may want to look into responsive design and setting breakpoints for different screen sizes.

Flex Wrap

If you want your content to stay a fixed size, you can have it wrap within your container. For different screen sizes, there may be more boxes in one row than another.

You'll likely need to change some styling, but wrapping would look something like this

<View style={styles.container}>
  <View style={styles.item} />
  <View style={styles.item} />
  <View style={styles.item} />
  <View style={styles.item} />
</View>

const styles = StyleSheet.create({
  container: {
    width: "100%",
    justifyContent: 'space-between',
    flexDirection: "row",
    alignItems: "center",
    flexWrap: 'wrap',
  },
  item: {
    width: 75,
    height: 75,
    marginRight: 10,
    backgroundColor: "red",
  },
});

Grid

If you don't like a variable number of boxes per row, you could make a grid. You would have a container, rows, and, in each row, your boxes.

Again, you'll have to tweak some styles.

<Container style={styles.container}>
  <Row style={styles.row}>
    <Box />
    <Box />
  <Row />
  <Row style={styles.row}>
    <Box />
    <Box />
  <Row />
</Container>

const styles = StyleSheet.create({
  container: {
    width: "100%",
  },
  row: {
    width: "100%",
    justifyContent: 'space-between',
    flexDirection: "row",
    alignItems: "center",
  },
  item: {
    width: 75,
    height: 75,
    marginRight: 10,
    backgroundColor: "red",
  },
});
JWilk
  • 48
  • 5
  • The thing is that the children have to be squares – Raul Sep 09 '20 at 14:51
  • 1
    Ah, that's a little trickier, but you might try to flex wrap your squares in your container. Let me see if I can find a good example. – JWilk Sep 09 '20 at 14:54
  • 1
    set padding-top like this: https://www.w3schools.com/howto/howto_css_aspect_ratio.asp then you can stick with percentages – Chaz Sep 09 '20 at 15:00
  • @JWilk I did it before, but with this if the screen is extremly small the children go out of the screen. Anyways, this work for most of the cases so I will accept this answer. – Raul Sep 09 '20 at 15:07
  • @Raul Feel free to hold out if you want. I don't care about internet points :p. You might try making your boxes rems instead so their sizes are relative. – JWilk Sep 09 '20 at 15:09
  • 1
    See my solution. Also, you can try to measure the parent as @JWilk said but unnecessary with aspectRatio – Victor Molina Sep 09 '20 at 15:10
  • 1
    @Raul I'm mistaken about rems, since this is react native. Victor's aspectRatio solution solution may be better. If you decide to use measurements, I made a measurement hook for that: https://stackoverflow.com/a/63767950/14231183 – JWilk Sep 09 '20 at 15:14