134

I'm creating a form in React Native and would like to make my TextInputs 80% of the screen width.

With HTML and ordinary CSS, this would be straightforward:

input {
    display: block;
    width: 80%;
    margin: auto;
}

Except that React Native doesn't support the display property, percentage widths, or auto margins.

So what should I do instead? There's some discussion of this problem in React Native's issue tracker, but the proposed solutions seem like nasty hacks.

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
  • 1
    `react-native` uses `flex` for elements' sizes and positions. I am not sure but may be `flex-basis` is what you need: Check [this](https://developer.mozilla.org/en-US/docs/Web/CSS/flex-basis) and [this](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) – alioguzhan Nov 26 '15 at 13:38
  • 1
    And according to [this issue](https://github.com/facebook/react-native/issues/364) something like `flex: 0.8` may do the work. – alioguzhan Nov 26 '15 at 13:46
  • Note: https://stackoverflow.com/questions/74344593/make-top-div-20-and-bottom-div-80-of-parent-in-react-js – Chanrithisak Phok Nov 07 '22 at 09:49

10 Answers10

127

As of React Native 0.42 height: and width: accept percentages.

Use width: 80% in your stylesheets and it just works.

  • Screenshot

  • Live Example
    Child Width/Height as Proportion of Parent

  • Code

    import React from 'react';
    import { Text, View, StyleSheet } from 'react-native';
    
    const width_proportion = '80%';
    const height_proportion = '40%';
    
    const styles = StyleSheet.create({
      screen: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
        backgroundColor: '#5A9BD4',
      },
      box: {
        width: width_proportion,
        height: height_proportion,
        alignItems: 'center',
        justifyContent: 'center',
        backgroundColor: '#B8D2EC',
      },
      text: {
        fontSize: 18,
      },
    });
    
    export default () => (
      <View style={styles.screen}>
        <View style={styles.box}>
          <Text style={styles.text}>
            {width_proportion} of width{'\n'}
            {height_proportion} of height
          </Text>
        </View>
      </View>
    );
    
GollyJer
  • 23,857
  • 16
  • 106
  • 174
97

That should fit your needs:

var yourComponent = React.createClass({
    render: function () {
        return (
            <View style={{flex:1, flexDirection:'column', justifyContent:'center'}}>
                <View style={{flexDirection:'row'}}>
                    <TextInput style={{flex:0.8, borderWidth:1, height:20}}></TextInput>
                    <View style={{flex:0.2}}></View> // spacer
                </View>
            </View>
        );
    }
});
neciu
  • 4,373
  • 2
  • 24
  • 33
54

If you are simply looking to make the input relative to the screen width, an easy way would be to use Dimensions:

// De structure Dimensions from React
var React = require('react-native');
var {
  ...
  Dimensions
} = React; 

// Store width in variable
var width = Dimensions.get('window').width; 

// Use width variable in style declaration
<TextInput style={{ width: width * .8 }} />

I've set up a working project here. Code is also below.

https://rnplay.org/apps/rqQPCQ

'use strict';

var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TextInput,
  Dimensions
} = React;

var width = Dimensions.get('window').width;

var SampleApp = React.createClass({
  render: function() {
    return (
      <View style={styles.container}>
        <Text style={{fontSize:22}}>Percentage Width In React Native</Text>
        <View style={{marginTop:100, flexDirection: 'row',justifyContent: 'center'}}>
            <TextInput style={{backgroundColor: '#dddddd', height: 60, width: width*.8 }} />
          </View>
      </View>
    );
  }
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop:100
  },

});

AppRegistry.registerComponent('SampleApp', () => SampleApp);
Nader Dabit
  • 52,483
  • 13
  • 107
  • 91
  • 6
    The React Native docs should mention the Dimensions package on the front page - that it doesn't astounds me... – A A Karim Aug 17 '16 at 10:48
  • very valuable answer. Dimensions is actually very useful. Note: "Although dimensions are available immediately, they may change (e.g due to device rotation) so any rendering logic or styles that depend on these constants should try to call this function on every render, rather than caching the value (for example, using inline styles rather than setting a value in a StyleSheet)." – Philip E Mar 14 '18 at 09:52
  • Note that using Dimensions breaks your layouts post screen rotation if you support landscape and don't handle those layout changes manually. – ratsimihah Sep 04 '18 at 11:09
33

In your StyleSheet, simply put:

width: '80%';

instead of:

width: 80%;

Keep Coding........ :)

Krishna Raj Salim
  • 7,331
  • 5
  • 34
  • 66
13

You can also try react-native-extended-stylesheet that supports percentage for single-orientation apps:

import EStyleSheet from 'react-native-extended-stylesheet';

const styles = EStyleSheet.create({
  column: {
    width: '80%',
    height: '50%',
    marginLeft: '10%'
  }
});
vitalets
  • 4,675
  • 1
  • 35
  • 35
5

The technique I use for having percentage width of the parent is adding an extra spacer view in combination with some flexbox. This will not apply to all scenarios but it can be very helpful.

So here we go:

class PercentageWidth extends Component {
    render() {
        return (
            <View style={styles.container}>
                <View style={styles.percentageWidthView}>
                    {/* Some content */}
                </View>

                <View style={styles.spacer}
                </View>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flexDirection: 'row'
    },

    percentageWidthView: {
        flex: 60
    },

    spacer: {
        flex: 40
    }
});

Basically the flex property is the width relative to the "total" flex of all items in the flex container. So if all items sum to 100 you have a percentage. In the example I could have used flex values 6 & 4 for the same result, so it's even more FLEXible.

If you want to center the percentage width view: add two spacers with half the width. So in the example it would be 2-6-2.

Of course adding the extra views is not the nicest thing in the world, but in a real world app I can image the spacer will contain different content.

dsdeur
  • 159
  • 2
  • 3
  • you can imagine the spacer will contain different content? why? i can think of plenty examples where a spacer is just filler html. – AlxVallejo Jun 27 '17 at 22:05
2

I have an updated solution (late 2019) , to get 80% width of parent Responsively with Hooks it work's even if the device rotate.

You can use Dimensions.get('window').width to get Device Width in this example you can see how you can do it Responsively

import React, { useEffect, useState } from 'react';
import { Dimensions , View , Text , StyleSheet  } from 'react-native';

export default const AwesomeProject() => {
   const [screenData, setScreenData] = useState(Dimensions.get('window').width);

    useEffect(() => {
     const onChange = () => {
     setScreenData(Dimensions.get('window').width);
     };
     Dimensions.addEventListener('change', onChange);

     return () => {Dimensions.removeEventListener('change', onChange);};
    });

   return (  
          <View style={[styles.container, { width: screenData * 0.8 }]}>
             <Text> I'mAwesome </Text>
           </View>
    );
}

const styles = StyleSheet.create({
container: {
     flex: 1,
     alignItems: 'center',
     justifyContent: 'center',
     backgroundColor: '#eee',
     },
});
Shayan Moghadam
  • 1,860
  • 2
  • 10
  • 19
2

The easiest way to achieve is by applying width to view.

width: '80%'
Kushal Desai
  • 119
  • 2
  • 11
1

This is the way I got the solution. Simple and Sweet. Independent of Screen density:

export default class AwesomeProject extends Component {
    constructor(props){
        super(props);
        this.state = {text: ""}
    }
  render() {
    return (
       <View
          style={{
            flex: 1,
            backgroundColor: "#ececec",
            flexDirection: "column",
            justifyContent: "center",
            alignItems: "center"
          }}
        >
          <View style={{ padding: 10, flexDirection: "row" }}>
            <TextInput
              style={{ flex: 0.8, height: 40, borderWidth: 1 }}
              onChangeText={text => this.setState({ text })}
              placeholder="Text 1"
              value={this.state.text}
            />
          </View>
          <View style={{ padding: 10, flexDirection: "row" }}>
            <TextInput
              style={{ flex: 0.8, height: 40, borderWidth: 1 }}
              onChangeText={text => this.setState({ text })}
              placeholder="Text 2"
              value={this.state.text}
            />
          </View>
          <View style={{ padding: 10, flexDirection: "row" }}>
            <Button
              onPress={onButtonPress}
              title="Press Me"
              accessibilityLabel="See an Information"
            />
          </View>
        </View>
    );
  }
}
AlainIb
  • 4,544
  • 4
  • 38
  • 64
sagar suri
  • 4,351
  • 12
  • 59
  • 122
0

Just add quotes around the size in your code. Using this you can use percentage in width, height

input: {
    width: '80%'
}
Manas Sanas
  • 342
  • 9
  • 18