Search code examples
javascriptreact-nativemargin

Weird Margin behavior in React Native in combination with absolute position


I'm trying to position View elements in react native that have the position: "absolute" attribute in their parent container, but the positive and negative values seem not to be consistent. Let me show you by an example:

function Home(props) {
    return (
        <View style={{ justifyContent: "center", alignItems: "center", flex: 1 }}>
            <View style={{ position: "absolute" }}>
                <View style={{ backgroundColor: "blue", width: 100, height: 100 }}></View>
            </View>
            <View style={{ position: "absolute" }}>
                <View style={{ backgroundColor: "yellow", width: 100, height: 100, marginTop: 200 }}></View>
            </View>
            <View style={{ position: "absolute" }}>
                <View style={{ backgroundColor: "red", width: 100, height: 100, marginTop: -200 }}></View>
            </View>
        </View>
    );
}

which produces an output that looks like this:

enter image description here

So I have three View elements packed in another View that has the position: "absolute" attribute. The first (blue) has no margin so it is exactly in the middle, the second (yellow) has a positive top margin of 200 and the third (red) a negative top margin of 200. It seems to be very odd why the red rectangle is further away than the yellow.

A marginTop: 200 and marginTop: -150 seem to have the same effect (in opposite directions). What is the problem here?


Solution

  • The reason for this is because you're using marginTop instead of top. The problem with margin and absolute positioning here is that you're actually changing the size of the parent of the colored boxes even if it doesn't look like it, instead of moving the colored boxes by a certain amount from the center.

    So you're probably looking for something like this instead:

    function Home(props) {
      return (
        <View style={{justifyContent: 'center', alignItems: 'center', flex: 1}}>
          <View style={{position: 'absolute'}}>
            <View style={{backgroundColor: 'blue', width: 100, height: 100}}></View>
          </View>
          <View style={{position: 'absolute'}}>
            <View
              style={{
                backgroundColor: 'yellow',
                width: 100,
                height: 100,
                top: 200,
              }}></View>
          </View>
          <View style={{position: 'absolute'}}>
            <View
              style={{
                backgroundColor: 'red',
                width: 100,
                height: 100,
                top: -200,
              }}></View>
          </View>
        </View>
      );
    }
    

    To explain it differently: You're not really moving the colored boxes, but you're modifying the space on top of the colored boxes which pushes the boxes down.


    If you add a borderWidth to the views around the different boxes you can see the effect that adding the margin to the box views has on the parent views.