100

I've want to achieve the following:

enter image description here

The following images are what I can do right now, but that's NOT what I want. scenarioAscenarioB

Sample of code I have right now:

renderA() {
    return (
        <View style={ position: 'absolute', zIndex: 0 }>    // parent of A
            <View style={ zIndex: 2 }>  // element A
            </View>
            <View style={ zIndex: 2 }>  // element A
            </View>
        </View>
    );
}

renderB() {
    return (
        <View style={ position: 'absolute', zIndex: 1 }>    // element B
        </View>
    );
}


render() {
    return (
        <View>
            {this.renderA()}
            {this.renderB()}
        </View>
    );
}

To put it in words, I want

  • Parent A: to be below everything.
  • Element B: to be at the above parent A but below element A.
  • Element A: above everything.

Note that Parent A and Element B both have to be absolutely positioned, and both elements A and elements B have to be clickable...!

David Schumann
  • 13,380
  • 9
  • 75
  • 96
SudoPlz
  • 20,996
  • 12
  • 82
  • 123

7 Answers7

94

Use elevation instead of zIndex for android devices

elevatedElement: {
  zIndex: 3, // works on ios
  elevation: 3, // works on android
}

This worked fine for me!

Syntle
  • 5,168
  • 3
  • 13
  • 34
  • 20
    You just ended a full day of debugging on Android. "elevation" on Android, not "zIndex". Argh! This seems like a deviation from standard CSS. "elevation" is supposed to affect drop shadows and such; aeshetic only, and not comparable with z-index. – Artif3x Oct 06 '20 at 20:44
  • 5
    For me, the elevation only fixes the problem visually, i.e. the previously hidden elements are now visible, but at this state they are not interactive any more (i.e. buttons etc cannot be clicked). The only solution (for Android at least) seems to be the appropriate ordering of elements. – Darko Maksimovic Jan 18 '21 at 17:20
54

I believe there are different ways to do this based on what you need exactly, but one way would be to just put both Elements A and B inside Parent A.

<View style={{ position: 'absolute' }}>    // parent of A
  <View style={{ zIndex: 1 }} />  // element A
  <View style={{ zIndex: 1 }} />  // element A
  <View style={{ zIndex: 0, position: 'absolute' }} />  // element B
</View>
Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
Matt Aft
  • 8,742
  • 3
  • 24
  • 37
  • 1
    I thought of that, but I have to keep the structure as is..! There's a good reason why I don't want to add elements B in the parent of A view. I simplified my question, but there are lots of **parent of A** Views containing lots of element A's. I appreciate the answer though, thanks. – SudoPlz Jan 30 '17 at 19:13
  • I don't think it's possible to do it the way you want it. The parent's Z-index will be evaluated first, then the children will be compared to other children. Here is a similar post the goes into more detail: http://stackoverflow.com/questions/7490146/z-index-relative-or-absolute – Matt Aft Jan 30 '17 at 19:39
  • Hmm, I was thinking something like keep the last image (3rd scenario) but i.e disregard touches on the *parent A* (which will be transparent anyway) and let the event pass to *element B* even if it's below *parent A*. And of course if *element A* is rendered, it should always receive the touch handler. – SudoPlz Jan 30 '17 at 19:54
  • Actually, that might work...set pointerEvents to 'box-none' on the parent A. This will make elements A clickable, and you will be able to click through the parent to reach element B behind it. – Matt Aft Jan 30 '17 at 23:34
  • 1
    add least use proper syntax... style={{ }} – Greg Benner Nov 10 '17 at 18:22
  • That doesn't work on Android, element B will get cropped because parent A is not wide enough. – SudoPlz May 30 '19 at 18:25
  • Also, for anyone coming here because iOS doesn't seem to care about the zIndex, check that both elements are siblings, see the comment at the bottom of this page https://reactnative.dev/docs/layout-props#zindex, "On iOS, zIndex may require Views to be siblings of each other for it to work as expected." – JoshJoe Jun 14 '21 at 14:46
5

I finally solved this by creating a second object that imitates B.

My schema now looks like this:

enter image description here

I now have B1 (within parent of A) and B2 outside of it.

B1 and B2 are right next to one another, so to the naked eye it looks as if it's just 1 object.

SudoPlz
  • 20,996
  • 12
  • 82
  • 123
  • 20
    That seems more like a kluge than a reproducible solution. Anyone have a more engineered solution? – Mike S. May 05 '18 at 20:47
  • 2
    I thought you said you don't want B to be inside parent of A. How is this better than the most upvoted answer? – Nikola Mihajlović May 28 '19 at 12:47
  • https://stackoverflow.com/questions/41943191/how-to-use-zindex-in-react-native/42654930?noredirect=1#comment99367539_41943372 – SudoPlz May 30 '19 at 18:30
3

UPDATE: Supposedly, zIndex has been added to the react-native library. I've been trying to get it to work without success. Check here for details of the fix.

Mike S.
  • 2,048
  • 1
  • 32
  • 55
  • 5
    It works as intended. After playing around with it a bit, I figured out how to use it correctly. Styling for mobile has always *appeared* deceptively simple but in truth is not. – Mike S. May 19 '18 at 13:59
1

You cannot achieve the desired solution with CSS z-index either, as z-index is only relative to the parent element. So if you have parents A and B with respective children a and b, b's z-index is only relative to other children of B and a's z-index is only relative to other children of A.

The z-index of A and B are relative to each other if they share the same parent element, but all of the children of one will share the same relative z-index at this level.

1pocketaces1
  • 137
  • 1
  • 11
0

You can use the Elevation property in your StyleSheet

containerText: {
    elevation: 3,
    backgroundColor: '#FB8500',
    padding: 3,
    borderRadius: 15,
    marginTop: -30,
    marginLeft: -10,
  },
0

Try to use zIndex for iOS and elevation for android devices to stack the view on top of one another.

element: {
  zIndex: 1, // 1 for stacking the element on top of the previous element and -1 
             // for stacking the element under the above previous element.
  elevation: 1,
}
Codemaker2015
  • 12,190
  • 6
  • 97
  • 81