react-native: [Android] position: absolute shouldn't be cut off within a container with border

Description

If you have an element position: absolute with negative offset within a container with a border, it’s going to be cut off, it’s like overflow: hidden of the container is suddenly enabled by the border. But if you remove the border of the container, it works well. This issue only happens on Android.

#3198 is a similar issue, and was reported with lots of discussions. However, I believe they are not exactly the same.

Reproduction

I’ve made an example on rnplay to reproduce the issue.

Solution

TBD

Additional Information

  • React Native version: 0.33 (rnplay), 0.39 (the version I currently use)
  • Platform: Android
  • Operating System: MacOS

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Reactions: 93
  • Comments: 69 (10 by maintainers)

Most upvoted comments

Workaround

Use an extra container and fake the overflow with it: https://snack.expo.io/@designorant/overflow-visible-android-workaround

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

export default class App extends Component {
  render() {
    return (
      <View style={styles.mainContainer}>

        <View style={styles.componentContainer}>
          <View style={[styles.element, styles.element1]} />
          <Text style={styles.text}>overflow: "visible"</Text>
        </View>

        <View style={styles.extraComponentContainer}>
          <View style={[styles.element, styles.element2]} />
          <View style={styles.componentContainer}>
            <Text style={styles.text}>extra container workaround</Text>
          </View>
        </View>

      </View>
    );
  }
}

const styles = StyleSheet.create({
  mainContainer: {
    flex: 1,
    alignItems: "center",
    justifyContent: "space-around"
  },
  componentContainer: {
    backgroundColor: "#d3d3d3",
    borderWidth: 1,
    borderColor: "grey",
    width: 200,
    height: 200,
    position: "relative",
    overflow: "visible" // doesn't do anything
  },
  extraComponentContainer: {
    // fakes overflow but requires more markup
    backgroundColor: "#ffff00",
    paddingTop: 20,
    paddingLeft: 20,
    paddingBottom: 20,
    paddingRight: 20,
    position: "relative"
  },
  element: {
    backgroundColor: "#ff0000",
    width: 40,
    height: 40
  },
  element1: {
    position: "absolute",
    top: -20,
    left: -20
  },
  element2: {
    position: "absolute",
    top: 0,
    left: 0,
    zIndex: 100,
    elevation: 100
  },
  text: {
    textAlign: "right",
    backgroundColor: "transparent"
  }
});

overflowvisible

Still an issue 😭

Any solution for this issue? I have also experience it on android development.

after some testing, it also happened when container has these styles

  • backgroundColor
  • borderColor
  • zIndex

Facing this as well 😦

image

Works great on iOS:

image

And still an issue.

I fix it setting a elevation together the position.

elevation : 10, position: “absolute”

For me the problem occurred with “Angular Material” on Tabs component, I put “overflow: visible !important;” on all containers and I finally found it!

If I add these classes, it works!

.mat-tab-body-wrapper { overflow: visible !important; }

.mat-tab-body.mat-tab-body-active { overflow: visible !important; }

anyone comes to save us~

+1 also having this issue.

Still an issue

Yes, react native has the pointerEvents prop.

Still an issue for me.

This is an issue for me as well.

Yeah this is currently happening with me even when the containing view has no border nor border-radius. This is definitely an issue because, for example, I want to show a circular icon on the top + middle area of my modal window. You can see it getting cut off below:

image

Still an issue

@Nagibaba Thanks for this. I create snack with this approach https://snack.expo.io/@denisdov/android-overflow-fix

Still an issue…

I added a faker container: <View style={{position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, borderRadius: 4, backgroundColor: 'rgba(255,255,255, .15)', zIndex: 1 }} />. Don’t use borderRadius, backgroundColor, zIndex in real container, but only in fake container.

<View style={s.realContainer } > <View style={{position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, borderRadius: 4, backgroundColor: 'rgba(255,255,255, .15)' }} /> <Image /> </View>

If some have a solution for that it’s should be great. My java android skill is not good enough to make a PR 😦

@fabriziobertoglio1987 does this count as negative margins? it’s absolute positioning, not margin?

And I can concur, negative margins will break your layouts across android devices in React Native, I’ve seen it happen in prod =)

@iway1 as explained by @sibelius, It is caused by ViewGroup#setClipChildren

Read more at https://medium.com/entria/solving-view-overflow-in-android-reactnative-f961752a75cd

THIS HAS WORKED FOR ME 100%

import React from ‘react’; import { StyleSheet, View, Text, ScrollView, Image, SafeAreaView, StatusBar, TextInput, Dimensions} from ‘react-native’;

const WIDTH = Dimensions.get(‘window’).width; const HEIGHT = Dimensions.get(‘window’).height; export default class App extends React.Component {

render() {
  return (
    <ScrollView horizontal={false} showsVerticalScrollIndicator={false}>

    
        <View style={styles.container}>
        <View style={styles.recent}>
         <Text>Recent</Text>
        </View>
        
        </View>

        
     
       
    
    </ScrollView>
  );
}

}

const styles = StyleSheet.create({

container:{
   flex:1,
   width:WIDTH,
   height:HEIGHT,
   overflow:'visible',
   position:'relative',
},

recent:{
  width:'100%',
  height:30,
  position:'absolute',
  top:100,
  left:40,
  backgroundColor:'#eee',


},

});

still an issue

To overcome this issue you can render a absolute positioned view with your background color on Android. Following code will work on android 😃

      <View style={{ flex: 1, backgroundColor: 'red' }}>
        <View style={{ height: 200, backgroundColor: 'green' }} />
        <View style={{ height: 200 }}>
          <View style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'yellow' }} />
          <View style={{ height: 50, width: 50, backgroundColor: 'aqua', position: 'absolute', top: -20 }} />
        </View>
      </View>

@brunolemos thanks! We did manage to fix out issue with poitnerEvents="box-none" and position absolute

I have this problem too in rn 0.51.0.

@designorant Thanks Michal for your advice! One question remains: Wouldn’t the “extraComponentContainer” prevent clicks/actions/events to elements/components below it?

I know in css there is “pointer-events”. When its set to “none” (e.g. pointer-events: none; ) The elements lets all events pass through to other elements below it. Anything like that in react-native?