React-native: Why doesn't support zIndex?

Created on 6 Apr 2015  ·  19Comments  ·  Source: facebook/react-native

I build a component, but i can not set z-index invariant violation: 'zIndex' is not a valid style property. @vjeux

'use strict';

var React = require('react-native');

var {
  ActivityIndicatorIOS,
  StyleSheet,
  Text,
  View
} = React;

var Loading = React.createClass({
  render: function () {
    return (
      <View style={ styles.container }>
        <View style={ styles.loading }>
          <ActivityIndicatorIOS style={ styles.animate } animating={ true }></ActivityIndicatorIOS>
          <Text style={ styles.text }>Loading...</Text>
        </View>
      </View>
    );
  }
});

var styles = StyleSheet.create({
  container: {
    zIndex: 1,
    position: 'absolute',
    alignItems: 'center'
  },

  loading: {
    width: 94,
    height: 94,
    padding: 15,
    opacity: .5,
    borderRadius: 4,
    backgroundColor: 'black'
  },

  animate: {
    marginBottom: 15
  },

  text: {
    color: '#FFF'
  }

});

module.exports = Loading;

Thanks!

Locked

Most helpful comment

I know this is closed, but this is preventing something as simple as a dropdown from being implementable?

The only way I can think of doing one is to have 1 single View at the bottom of all my other views that happens to hold my options, that I move around across the app depending on which drop-down might need it. That seems really hacky.

All 19 comments

zIndex can be controlled by re-arranging the components when you render. The later views will be drawn above the earlier ones.

This is easier for debugging because you only need to look at the render order, instead of needing to check the render order _and_ the stylesheet.

559, #131

Thank you very much! : )

Well i know it's closed but it's very useful to have these properties bringSubviewToFront and inverse

See The PR https://github.com/facebook/react-native/pull/1891

The problem with changing the order in which you draw items is that it can have unexpected results on animation.

Anyone know how to control the draw order without reordering siblings?

UIView.subviews

The order of the subviews in the array reflects their visible order on the screen, with the view at index 0 being the back-most view.

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/occ/instp/UIView/subviews

One way to deal with the problems that are created by automatically overlaying subsequent elements over previous ones would be to implement the flex order element. This way, you could have an element with a lower z-index easily appear after an element with a higher z-index.

Flex order seems like a great idea cc @vjeux. Anyone want to contribute a PR and some tests to the CSS-layout repo?

flex order would not suffice layering to some extend. I got two list view. Overlapping each other. The list view which is below won't scroll at all as it being overlapped by high order. I gave a shot by making position: absolute and giving top and bottom a value. it did not work, so was wondering, if any one can show me a way to this mystery.

Can you add it to https://productpains.com/product/react-native/, so that we can track it and see how popular this is. Thanks!

I know this is closed, but this is preventing something as simple as a dropdown from being implementable?

The only way I can think of doing one is to have 1 single View at the bottom of all my other views that happens to hold my options, that I move around across the app depending on which drop-down might need it. That seems really hacky.

I am in the same boat. I have a deeply nested component that needs to render an overlay. Conceptually, it makes sense to handle the generation of this overlay and its contents, and the handling of open close, all within this component. However, due to the zindex issue, it is impossible to get it to render on top because it is so deeply nested.

To overcome this, I have to move the generation and rendering functionality into a separate component higher up in the tree, while keeping the trigger functionality in the deeply nested component. However, multiple nested components need this overlay, with different options, so it begins to turn into a mess. The app is losing separation of concerns.

d64368b adds zIndex to iOS
3d3b067 adds zIndex to Android

Yes, however, I still run into this issue. Between my top-most layer and my bottom-most layer of the component tree, there are multiple components in-between that are bound to be positioned absolute or fixed. For example, tab navigation on the left or bottom of the app must be pinned there to prevent movement, generally using fixed.

Therefore, applying position: absolute + the highest zIndex value known within the app, to a component at the bottom layer, is NOT forcing the component to render at the top (especially above the aforementioned tab navigation). Because instead, it binds to the first position: absolute or fixed layer it finds on its way up the tree. Does that help clarify?

@joncursi That's how the web works too.

I suggest you create a portal component at the root which renders your components.

Does this work for Animated.View? I'm having a strange issue:

http://stackoverflow.com/questions/40326822/drag-drop-and-swap-items-animation

It works for simple cases e.g.:

<View style={{ zIndex: 100, backgroundColor: 'red' }}><Text>foo</Text></View>
<View style={{ zIndex: -100, top: -10, backgroundColor: 'blue' }}><Text>bar</Text></View>

but have no idea what's wrong for the animation. (Dragging should put it on top) The color change works, so I'd assume the zIndex should.
dragdropswap2

@andrewnoh zIndex only affects the order of siblings.

In your scenario, you need to change zIndex on the green boxes, instead of the draggable boxes (assuming the green box is the draggable box's parent).

@aleclarson Thank you so much. Seems like I had a pretty big misunderstanding about how zIndex works. 👍

dragdropswap3

I have a dropdown Menu which is being overlapped by text view, zIndex does not work

screenshot_2017-07-10-12-31-11-404_com firstproject

`

import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
TextInput,
TouchableOpacity,
Image
} from 'react-native';

import DropDown, {
Select,
Option,
OptionList,
updatePosition
} from 'react-native-dropdown';

import { StackNavigator } from 'react-navigation';
export default class Corporate extends Component {

//=======navigation optionpane========//
static navigationOptions = {
title: 'Welcome',
header: null
};
//====================================//

constructor(props) {
super(props);

this.state = {
  canada: '',
};

}

componentDidMount() {
updatePosition(this.refs['SELECT1']);
updatePosition(this.refs['OPTIONLIST']);
}

_getOptionList() {
return this.refs['OPTIONLIST'];
}

_canada(province) {

this.setState({
  ...this.state,
  canada: province
});

}

renderA() {
return (



);
}

renderB() {
return (

  <View >

    <Select
      style={{ position: 'relative', zIndex: 20 }}
      width={300}
      ref="SELECT1"
      optionListRef={this._getOptionList.bind(this)}
      defaultValue="Select a Province in Canada ..."
      onSelect={this._canada.bind(this)}>
      <Option value={{ id: "alberta" }}>Alberta</Option>
      <Option>British Columbia</Option>
      <Option>Manitoba</Option>
      <Option>New Brunswick</Option>
      <Option>Newfoundland and Labrador</Option>

    </Select>


    <OptionList ref="OPTIONLIST" />




  </View>


);

}

renderC() {
return (
placeholder="Company"
secureTextEntry
style={styles.input}
underlineColorAndroid="transparent" />

placeholder="Email/Employee Id"
secureTextEntry
style={styles.input}
underlineColorAndroid="transparent" />

placeholder="Password"
secureTextEntry
style={styles.input}
underlineColorAndroid="transparent" />

placeholder="Referral Code(Option)"
secureTextEntry
style={styles.input}
underlineColorAndroid="transparent" />

    <TouchableOpacity activeOpacity={.5}>
      <View style={styles.button}>
        <Text style={styles.buttonText} > Submit</Text>
      </View>
    </TouchableOpacity>
  </View>
);

}

render() {
return (

  <View style={styles.container}>


    {this.renderA()}
    {this.renderB()}
    {this.renderC()}


  </View>


);

}
}
const styles = StyleSheet.create({
container: {

flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#000000'

},
image: {
width: 250,
height: 110
},
text: {
color: "#FFF",
fontSize: 25
},

inputWrap: {

marginVertical: 10,
height: 40,
width: 300,
marginTop: 20,
backgroundColor: "#FF0000"

},
input: {
flex: 1,
paddingHorizontal: 15,
backgroundColor: '#fff'
},
button: {
backgroundColor: "#FF8C00",
paddingVertical: 15,
marginVertical: 15,
marginHorizontal: 120,
width: 100,
height: 35,
alignItems: "center",
justifyContent: "center"
},
buttonText: {
color: '#FFF',
fontSize: 15
},

set: {
marginTop: 20
},
spinner: {

marginVertical: 10,
justifyContent: 'center',
alignItems: 'center',
marginTop: 20,
backgroundColor: "#FF0000"

}
});`

@khushdeepkaur In the future, consider creating a Gist when you have a lot of code to share. Also, you should open a new issue. This is an issue about perceived lack of support for zIndex, which has been resolved.

@ide @vjeux Should this thread be locked?

Was this page helpful?
0 / 5 - 0 ratings