'React native styling. width: percentage - number

I want to do width: 100% - 50 so I can add an icon which is 50 wide on the right hand side of it.

I have got width: 100% - 20% working by using react-native-extended-styles but I don't see why that is useful because you can do width: '80%'. I cannot get width: 100% - 50 working. Is there a way?

Trying to use the onLayout event to get the container width, then set the <autocomplete> to 100% - 50 of the container width but it isn't working.

    let Location = (props) => {
      let locationInputElement

      const blur = () => {
        locationInputElement.blur()
      }

      let inputContainerWidth

      return (
        <View style={styles.formItem}>
          <View
            onLayout={(event) => {
              inputContainerWidth = event.nativeEvent.layout.width
              console.log(inputContainerWidth)
            }}

    <Autocomplete
              data={props.autocompleteResults.predictions}...
 style={{
            borderRadius: 8,
            backgroundColor: 'red',
            alignSelf: 'stretch',
            paddingLeft: 10,
            position: 'relative',
            ...styles.label,
            ...styles.labelHeight,
            width: inputContainerWidth - 50
          }}
        />
      </View>
    </View>
  )
}

It does console.log 335 when it console.logs inputContainerWidth but the width of the <autocomplete> is 100% still.



Solution 1:[1]

I'd agree with Viktor, you should be able to achieve this using Flex Box.

Here's something I put together: https://snack.expo.io/B1jDKOhyb

You set the flexDirection of the formRow to row, and then the first child (the holder View for your AutoComplete component to flex: 1. This makes it fill all available space. The next child View is your icon holder. Which you can set to whatever value you want (in this case 50).

export default class App extends Component {
  render() {
    return (
      <View style={styles.container}>
        <View style={styles.formRow}>
          <View style={styles.formItem}>
            // AutoComplete component goes here
          </View>
          <View style={styles.formIcon}>
           // Icon goes here
          </View>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 100
  },
  formRow: {
    flexDirection: 'row',
    height: 50,
  },
  formItem: {
    flex: 1,
    backgroundColor: 'dodgerblue',
  },
  formIcon: {
    width: 50,
    backgroundColor: 'greenyellow',
  },
});

Solution 2:[2]

This can easily be solved by using Dimensions.

import { Dimensions } from 'react-native';

const MyComponent = () => {
  return <Text style={{height: Dimensions.get('window').height - 100}}></Text>
};

export default MyComponent;

Solution 3:[3]

You can do it without computing width. Use marginHorizontal: 50 with width:100 or flex:1.

Your code not working because, it's rendered then inputContainerWidth updated. To make it work, there should be another render with new inputContainerWidth. So you can't use a stateless component. Change Location to regular component and add inputContainerWidth to state.

Solution 4:[4]

Consider using useWindowDimensions from react-native (see docs):

import { useWindowDimensions } from 'react-native';
const { height, width } = useWindowDimensions();

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mike
Solution 2 Community
Solution 3 Meysam Izadmehr
Solution 4 Tianhui Li