flex vs flexGrow vs flexShrink vs flexBasis in React Native?
Here's some test code to consider:
render() {
return <View style={{flex: 1,backgroundColor: "cornflowerblue"}}>
<View style={{backgroundColor: "chartreuse"}}><Text>Nothing (17px)</Text></View>
<View style={{flex: 0, backgroundColor: "yellow"}}><Text>flex: 0 (17px)</Text></View>
<View style={{flex: 0, flexBasis: 10, backgroundColor: "brown"}}><Text>flex: 0, flexBasis: 10 (10px)</Text></View>
<View style={{flex: 0, flexGrow: 1, backgroundColor: "orange"}}><Text>flex: 0, flexGrow: 1 (97px)</Text></View>
<View style={{flex: 0, flexShrink: 1, backgroundColor: "tan"}}><Text>flex: 0, flexShrink: 1 (17px)</Text></View>
<View style={{flex: 0, flexGrow: 1, flexBasis: 10, backgroundColor: "purple"}}><Text>flex: 0, flexGrow: 1, flexBasis: 10 (90px)</Text></View>
<View style={{flex: 0, flexShrink: 1, flexBasis: 10, backgroundColor: "gray"}}><Text>flex: 0, flexShrink: 1, flexBasis: 10 (10px with 7px hidden below the next element)</Text></View>
<View style={{flex: 1, backgroundColor: "blue"}}><Text>flex: 1 (80px)</Text></View>
<View style={{flex: 1, flexBasis: 10, backgroundColor: "cornsilk"}}><Text>flex: 1, flexBasis: 10 (90px)</Text></View>
<View style={{flex: 1, flexGrow: 1, backgroundColor: "red"}}><Text>flex: 1, flexGrow: 1 (80px)</Text></View>
<View style={{flex: 1, flexShrink: 1, backgroundColor: "green"}}><Text>flex: 1, flexShrink: 1 (80px)</Text></View>
<View style={{flex: 1, flexGrow: 1, flexBasis: 10, backgroundColor: "aqua"}}><Text>flex: 1, flexGrow: 1, flexBasis: 10 (90px)</Text></View>
<View style={{flex: 1, flexShrink: 1, flexBasis: 10, backgroundColor: "pink"}}><Text>flex: 1, flexShrink: 1, flexBasis: 10 (90px)</Text></View>
</View>;
}
Here's a screenshot of the above code:
Added width
and height
:
render() {
return <View style={{flex: 1,backgroundColor: "cornflowerblue"}}>
<View style={{flex: 0, backgroundColor: "orange"}}><Text>flex: 0 (17px)</Text></View>
<View style={{flex: 0, width: 700, height: 20, backgroundColor: "yellow"}}><Text>flex: 0, width: 700, height: 20 (20px)</Text></View>
<View style={{flex: 0, flexBasis: 10, width: 700, height: 20, backgroundColor: "brown"}}><Text>flex: 0, flexBasis: 10, width: 700, height: 20 (10px with 7px hidden below the next element)</Text></View>
<View style={{flex: 0, flexGrow: 1, width: 700, height: 20, backgroundColor: "orange"}}><Text>flex: 0, flexGrow: 1, width: 700, height: 20 (90px)</Text></View>
<View style={{flex: 0, flexShrink: 1, width: 700, height: 20, backgroundColor: "tan"}}><Text>flex: 0, flexShrink: 1, width: 700, height: 20 (20px)</Text></View>
<View style={{flex: 0, flexGrow: 1, flexBasis: 10, width: 700, height: 20, backgroundColor: "purple"}}><Text>flex: 0, flexGrow: 1, flexBasis: 10, width: 700, height: 20 (80px)</Text></View>
<View style={{flex: 0, flexShrink: 1, flexBasis: 10, width: 700, height: 20, backgroundColor: "gray"}}><Text>flex: 0, flexShrink: 1, flexBasis: 10, width: 700, height: 20 (10px with 7px hidden below the next element)</Text></View>
<View style={{flex: 1, backgroundColor: "orange"}}><Text>flex: 1 (70px)</Text></View>
<View style={{flex: 1, width: 700, height: 20, backgroundColor: "blue"}}><Text>flex: 1, width: 700, height: 20 (70px)</Text></View>
<View style={{flex: 1, flexBasis: 10, width: 700, height: 20, backgroundColor: "cornsilk"}}><Text>flex: 1, flexBasis: 10, width: 700, height: 20 (80px)</Text></View>
<View style={{flex: 1, flexGrow: 1, width: 700, height: 20, backgroundColor: "red"}}><Text>flex: 1, flexGrow: 1, width: 700, height: 20 (70px)</Text></View>
<View style={{flex: 1, flexShrink: 1, width: 700, height: 20, backgroundColor: "green"}}><Text>flex: 1, flexShrink: 1, width: 700, height: 20 (70px)</Text></View>
<View style={{flex: 1, flexGrow: 1, flexBasis: 10, width: 700, height: 20, backgroundColor: "aqua"}}><Text>flex: 1, flexGrow: 1, flexBasis: 10, width: 700, height: 20 (80px)</Text></View>
<View style={{flex: 1, flexShrink: 1, flexBasis: 10, width: 700, height: 20, backgroundColor: "pink"}}><Text>flex: 1, flexShrink: 1, flexBasis: 10, width: 700, height: 20 (80px)</Text></View>
</View>;
}
Here's a screenshot of the above code:
flex: 0
(default)
-
flex: 0
- Element takes the size of contents. According to the documentation it should be sized by setting
width
andheight
props but it seems to fit to contents if those aren't set.
- Element takes the size of contents. According to the documentation it should be sized by setting
-
flex: 0, flexBasis: {{px}}
- Element takes the size given by
flexBasis
- Element takes the size given by
-
flex: 0, flexGrow: 1
- With
flex: 0
andflexGrow: 1
; it's the same as adding the size of the contents (in the example above it's a ) to the size of an element that's set toflex: 1
. It's similar toflex: 1, flexBasis: 10
except instead of adding a number of pixels you're adding the size of the content.
- With
-
flex: 0, flexShrink: 1
- With
flex: 0
andflexShrink: 1
, the element seems to take the size of the content, in other words it's the same as justflex: 0
. I'll bet there are situations where it would be bigger than the content but I haven't see that yet.
- With
-
flex: 0, flexGrow: 1, flexBasis: {{px}}
- This is the same as
flex: 0, flexGrow: 1
except instead of adding the content size to aflex: 1
element it adds the given number of pixels.
- This is the same as
-
flex: 0, flexShrink: 1, flexBasis: {{px}}
- This is the same as
flex: 0, flexBasis: {{px}}
.
- This is the same as
-
flex: 0, height: {{px}}
- With
flex: 0
,height
is treated just likeflexBasis
. If there is both aheight
andflexBasis
are set,height
is ignored.
- With
flex: 1
-
flex: 1
- Element takes available space. See Layout Props documentation for more details
-
flex: 1, flexBasis: {{px}}
- With
flex: 1
andflexBasis: {{px}}
; the value offlexBasis
is added to the element's size. In other words, it's like taking aflex: 1
element and adding on the number of pixels set byflexBasis
. So if aflex: 1
element is 50px, and you addflexBasis: 20
the element will now be 70px.
- With
-
flex: 1, flexGrow: 1
- ignored
-
flex: 1, flexShrink: 1
- ignored
-
flex: 1, flexGrow: 1, flexBasis: {{px}}
- This is the same as
flex: 1, flexBasis: {{px}}
sinceflexGrow
is ignored.
- This is the same as
-
flex: 1, flexShrink: 1, flexBasis: {{px}}
- This is the same as
flex: 1, flexBasis: {{px}}
sinceflexShrink
is ignored.
- This is the same as
-
flex: 1, height: {{px}}
- With
flex: 1
,height
is ignored. UseflexBasis
instead.
- With
Here are my observations:
-
Trouble Shooting Tip: Make sure the parent view(s) are giving the children room to grow/shrink. Notice the
flex: 1
on the parent view, without it, all the children don't display as you'd expect. -
Trouble Shooting Tip: Don't use
Hot Reloading
when testing these values, it can display elements incorrectly after it's reloaded a few times. I recommend enablingLive Reload
or using command + r (a lot). - The default flex value is
flex: 0
. If you don't add a flex style value it defaults to 0. - Trouble Shooting Tip: if you're tryign to figure out why something isn't displaying like you think it should, start with the (most) parent element and make sure it's giving enough space to it's children to do what they need to do. In other words, try setting it to flex:1 and see if that helps, then go to the next child and repeat.
- It seems like
width
is always considered withflexDirection: "column"
no matter the other flex props. The same applies forheight
withflexDirection: "row"
. - After running these test, in general I would use
flexBasis
overheight
sinceflexBasis
trumpsheight
.