In React Native, how do I put a view on top of another view, with part of it lying outside the bounds of the view behind?

React Native

React Native Problem Overview


I'm trying to make a layout as per below with React Native.

enter image description here

How do I specify the position of B relative to A?

With iOS Interface Builder and autoconstraints, this can very explicitly be done and is a breeze. It's not so obvious how one might achieve this with React Native.

React Native Solutions


Solution 1 - React Native

Add the following style to the "floating" view:

position: 'absolute'

You may also need to add a top and left value for positioning.

Solution 2 - React Native

The above solutions were not working for me. I solved it by creating a View with the same background colour as the parent and added negative margin to move the image upwards.

<ScrollView style={{ backgroundColor: 'blue' }}>
  <View
    style={{
      width: '95%',
      paddingLeft: '5%',
      marginTop: 80,
      height: 800,
    }}>
    <View style={{ backgroundColor: 'white' }}>
      
      <Thumbnail square large source={{uri: uri}} style={{ marginTop: -30 }}/>
      <Text>Some Text</Text>
    </View>
  </View>
</ScrollView>

and I got the following result.

enter image description here

Solution 3 - React Native

You can use zIndex for placing a view on top of another. It works like the CSS z-index property - components with a larger zIndex will render on top.

You can refer: Layout Props

Snippet:

    <ScrollView>
          <StatusBar backgroundColor="black" barStyle="light-content" />
          <Image style={styles.headerImage} source={{ uri: "http://www.artwallpaperhi.com/thumbnails/detail/20140814/cityscapes%20buildings%20hong%20kong_www.artwallpaperhi.com_18.jpg" }}>
            <View style={styles.back}>
              <TouchableOpacity>
                <Icons name="arrow-back" size={25} color="#ffffff" />
              </TouchableOpacity>
            </View>
            <Image style={styles.subHeaderImage} borderRadius={55} source={{ uri: "https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Albert_Einstein_1947.jpg/220px-Albert_Einstein_1947.jpg" }} />
          </Image>

const styles = StyleSheet.create({
	container: {
		flex: 1,
		backgroundColor: "white"
	},
	headerImage: {
		height: height(150),
		width: deviceWidth
	},
	subHeaderImage: {
		height: 110,
		width: 110,
		marginTop: height(35),
		marginLeft: width(25),
		borderColor: "white",
		borderWidth: 2,
		zIndex: 5
	},

Solution 4 - React Native

You can use this OverlayContainer. The trick is to use absolute with 100% size. Check below an example:

// @flow

import React from 'react'
import { View, StyleSheet } from 'react-native'

type Props = {
  behind: React.Component,
  front: React.Component,
  under: React.Component
}

// Show something on top of other
export default class OverlayContainer extends React.Component<Props> {
  render() {
    const { behind, front, under } = this.props

    return (
      <View style={styles.container}>
        <View style={styles.center}>
          <View style={styles.behind}>
            {behind}
          </View>
          {front}
        </View>
        {under}
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    height: '100%',
    justifyContent: 'center',
  },
  center: {
    width: '100%',
    height: '100%',
    alignItems: 'center',
    justifyContent: 'center',
  },
  behind: {
    alignItems: 'center',
    justifyContent: 'center',
    position: 'absolute',
    left: 0,
    top: 0,
    width: '100%',
    height: '100%'
  }
})

Solution 5 - React Native

import React, {Component} from 'react';
import {StyleSheet, View} from 'react-native';


export default class App extends Component {
  render() {
    return (
       <View>// you need to wrap the two Views an another View
          <View style={styles.box1}></View>
          <View style={styles.box2}></View>
       </View> 
    );
  }
}

const styles = StyleSheet.create({
  box1:{
    height:100,
    width:100,
    backgroundColor:'red'
  },
  box2:{
    height:100,
    width:100,
    backgroundColor:'green',
    position: 'absolute',
    top:10,
    left:30

  },
});

Solution 6 - React Native

You can use react-native-view-overflow plugin for placing a view on top of another. It works like the CSS z-index property.

import ViewOverflow from 'react-native-view-overflow';

<ViewOverflow />
    <View style={[styles2.cardBox, { marginTop: 50 }]}>
    <View style={[styles2.cardItem]} >
      <Text style={styles2.cardHeader}>userList</Text>
    </View>
      <View style={[styles2.cardContent]}>
        <Text style={styles2.text}>overflow: "visible"</Text>
      </View>
      <View style={[styles2.cardItemFooter]} >
        <Text style={styles2.cardTextFooter}>...</Text>
      </View>
    </View>
  </ViewOverflow>

const styles2 = StyleSheet.create({
  cardBox: {
    borderLeftWidth: 0,
    borderTopWidth: 0,
    backgroundColor: "transparent",
    borderWidth: 1,
    borderColor: "#d0d0d0",
    width: '94%',
    alignSelf: 'center',
    height: 200,
    position: "relative",
    borderRadius: 15,
    overflow: "visible" // doesn't do anything
  },
  cardContent: {
    textAlign: "right",
    backgroundColor: "transparent",
    marginTop: 15,
    alignSelf: 'flex-end',
    padding: 5,
  },
  cardHeader: {
    color: '#fff',
    fontFamily: 'Vazir',
    fontSize: 12
  },
  cardItem: {
    backgroundColor: "#3c4252",
    borderRadius: 3,
    position: "absolute",
    top: -10,
    right: -5,
    width: 50,
    height: 20,
    paddingRight: 5,
  },
})

Solution 7 - React Native

The easiest way to achieve this is with a negative margin.

const deviceWidth = RN.Dimensions.get('window').width

a: {
  alignItems: 'center',
  backgroundColor: 'blue',
  width: deviceWidth,
},
b: {
  marginTop: -16,
  marginStart: 20,
},

Solution 8 - React Native

You can use elevation property for Android if you don't mind the shadow.

{
  elevation:1
} 

Solution 9 - React Native

Try this:

style = {{position: 'absolute', bottom: 20, left: 20, elevation: 100}}

Solution 10 - React Native

Based on the example above i've created a component which stacks all childeren on top of each other. You could even nest OverlayContainers inside OverlayContainers.

Usage:

<OverlayContainer>
    <View style={{backgroundColor:'red', width:150, height: 150}}></View>
    <View style={{backgroundColor:'yellow', width:50, height: 50}}></View>
    <Text>Just some text</Text>
</OverlayContainer>

Output:

Output

import React, { FC, PropsWithChildren } from 'react'
import { StyleSheet, View } from 'react-native'

export const OverlayContainer: FC<PropsWithChildren<unknown>> = (props) => {
    return (
        <View style={styles.container}>
            {props.children.map((child, index) => (
                <View style={styles.child} key={index}>
                    {child}
                </View>
            ))}
        </View>
    );
}
const styles = StyleSheet.create({
    container: {
        flex: 1,
        height: '100%',
    },
    child: {
        position: 'absolute',
        left: 0,
        top: 0,
        width: '100%',
        height: '100%'
    }
})

Solution 11 - React Native

<SafeAreaView style={{ flex: 1 }} >
  <View style={{ height: Dimensions.get('window').height / 2, backgroundColor: 'blue', justifyContent: 'center' }}>
    <Text style={{ fontSize: 25, alignSelf: 'center' }} >A</Text>
      <View style={{ justifyContent: 'center', height: 100, width: 100, backgroundColor: 'yellow', position: 'absolute', left: 20, top: Dimensions.get('window').height / 2 - 70 }}>
        <Text style={{ fontSize: 22, alignSelf: 'center' }} >B</Text>
      </View>
  </View>
</SafeAreaView>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionfatuhokuView Question on Stackoverflow
Solution 1 - React NativeboredgamesView Answer on Stackoverflow
Solution 2 - React NativeAbdul Karim KhanView Answer on Stackoverflow
Solution 3 - React NativeThanmai CView Answer on Stackoverflow
Solution 4 - React Nativeonmyway133View Answer on Stackoverflow
Solution 5 - React NativeAvneesh AgrawalView Answer on Stackoverflow
Solution 6 - React NativeMahdi NobakhtView Answer on Stackoverflow
Solution 7 - React NativeCacheMeOutsideView Answer on Stackoverflow
Solution 8 - React NativeBora SumerView Answer on Stackoverflow
Solution 9 - React Nativeuser3595795View Answer on Stackoverflow
Solution 10 - React NativeuserM1433372View Answer on Stackoverflow
Solution 11 - React NativeAntier SolutionsView Answer on Stackoverflow