112

I am trying to resize an image (smaller to fit screen) in my react native app but am unable to do it as it is too big.

Here is the code:

'use strict';

var React = require('react-native');
var {
  StyleSheet,
  Text,
  TextInput,
  View,
  TouchableHighlight,
  ActivityIndicatorIOS,
  Image,
  Component
} = React;

var styles = StyleSheet.create({
  description: {
    marginBottom: 20,
    fontSize: 18,
    textAlign: 'center',
    color: '#656565'
  },
  container: {
    padding: 30,
    marginTop: 65,
    alignItems: 'center'
  },
  flowRight: {
    flexDirection: 'row',
    alignItems: 'center',
    alignSelf: 'stretch'
  },
  buttonText: {
    fontSize: 18,
    color: 'white',
    alignSelf: 'center'
  },
  button: {
    height: 36,
    flex: 1,
    flexDirection: 'row',
    backgroundColor: '#48BBEC',
    borderColor: '#48BBEC',
    borderWidth: 1,
    borderRadius: 8,
    marginBottom: 10,
    alignSelf: 'stretch',
    justifyContent: 'center'
  },
  searchInput: {
    height: 36,
    padding: 4,
    marginRight: 5,
    flex: 4,
    fontSize: 18,
    borderWidth: 1,
    borderColor: '#48BBEC',
    borderRadius: 8,
    color: '#48BBEC'
  },
  image: {
    width: 200,
    height: 220
  },
});

class SearchPage extends Component {
  render() {
    return (
      <View style={styles.container}>

        <Image source={require('image!rclogo')} style={styles.image}/>

        <Text style={styles.description}>
          Search for RCers!
        </Text>

        <Text style={styles.description}>
          Search
        </Text>

        <View style={styles.flowRight}>
          <TextInput
            style={styles.searchInput}
            placeholder='Search by Batch, Name, Interest...'/>
          <TouchableHighlight style={styles.button}
              underlayColor='#99d9f4'>
            <Text style={styles.buttonText}>Go</Text>
          </TouchableHighlight>
        </View>

        <TouchableHighlight style={styles.button}
            underlayColor='#99d9f4'>
          <Text style={styles.buttonText}>Location</Text>
        </TouchableHighlight>

      </View>
    );
  }
} 

I tried to take it out of the container tag but cannot seem to understand why it will not render properly?

Can this be done with flexbox resizeMode? How do you do it? I can't find any docs on it...

Patrik Prevuznak
  • 2,181
  • 15
  • 14
rahul2001
  • 1,577
  • 2
  • 17
  • 32

21 Answers21

160

image auto fix the View

image: {
    flex: 1,
    width: null,
    height: null,
    resizeMode: 'contain'
}
shixukai
  • 1,805
  • 1
  • 9
  • 8
  • 66
    This caused my image to disappear? – Karl Taylor Mar 12 '18 at 17:07
  • 6
    The image will need to be in a wrapping container such as a View. At some point you'll need to specify a size.... – Luke Apr 09 '18 at 03:06
  • 2
    If you're on Typescript, try `width: undefined` and `height: undefined` instead to prevent type errors. – blindbox Apr 30 '20 at 14:14
  • This worked for me in React Native. Although I changed resizeMode to 'cover'. This filled the entire screen with the Image. – NightTom Jun 05 '20 at 11:56
  • This is the perfect answer. I guess this method is better for the images larger than the View. – Dami Jan 20 '21 at 14:38
  • itemImageHolder: { width: '100%', aspectRatio: 1 / 1, borderRadius: 8, overflow: 'hidden', height: 180, }, itemImage: { flex: 1, width: "100%", aspectRatio: 1 / 1, resizeMode: "contain" }, – mlg Jul 02 '23 at 03:40
65

I adjust your answer a bit (shixukai)

image: {
    flex: 1,
    width: 50,
    height: 50,
    resizeMode: 'contain' }

When I set to null, the image wont show at all. I set to certain size like 50

Apit John Ismail
  • 2,047
  • 20
  • 19
54

This worked for me:

image: {
    flex: 1,
    aspectRatio: 1.5, 
    resizeMode: 'contain',

  }

aspectRatio is just width/height (my image is 45px wide x 30px high).

GenericJam
  • 2,915
  • 5
  • 31
  • 33
  • Thank you, this is the only solution that worked for me. I had images with both width and height flex-sized (bounded by the screen) and until I added aspectRatio, only the height was being sized properly and the width was the source image width (even though the parent had alignItems: 'stretch'). – Onyxite Jun 21 '18 at 19:05
  • This is the best solution. The only one that worked for me. – Stuart Mar 05 '19 at 13:56
  • How can you apply a border around the image doing this? It is creating a large amount of white space on either side. – kojow7 Jan 31 '20 at 04:28
17

After trying some combinations, I get this working like this:

image: {
    width: null,
    resizeMode: 'contain',
    height: 220
}

Specifically in that order. I hope this can be helpful for someone. (I know that is an old question)

14

Try this: (for more details click here)

image: { flex: 1, height: undefined, width: undefined, resizeMode: 'contain' }
Andrea Girardi
  • 4,337
  • 13
  • 69
  • 98
Sunil Tako
  • 377
  • 2
  • 13
11

This worked for me:

image: {
  flex: 1,
  width: 900,
  height: 900,
  resizeMode: 'contain'
}

Just need to make sure that the width and height are bigger than you need as it is limited to what you set.

anothernode
  • 5,100
  • 13
  • 43
  • 62
Jamie Hall
  • 276
  • 1
  • 3
  • 12
8

Ran into the same problem and was able to tweak the resize mode until I found something I was happy with. Alternative approaches include:

  • Reduce the size of the Static Resource using an image editor
  • Add a transparent border to the static resource using an image editor
  • Use a Network Resource at the expense of UX

To prevent loss of quality while tweaking images consider working with vector graphics so you can experiment with different sizes easily. Inkscape is free tool and works well for this purpose.

vhs
  • 9,316
  • 3
  • 66
  • 70
6

In my case I could not set 'width' and 'height' to null because I'm using TypeScript.

The way I fixed it was by setting them to '100%':

backgroundImage: {
    flex: 1,
    width: '100%',
    height: '100%',
    resizeMode: 'cover',        
}
Felipe Braz
  • 121
  • 1
  • 2
5

This worked for me,

image: {
    width: 200,
    height:220,
    resizeMode: 'cover'
}

You can also set your resizeMode: 'contain'. I defined the style for my network images as:

<Image 
   source={{uri:rowData.banner_path}}
   style={{
     width: 80,
     height: 80,
     marginRight: 10,
     marginBottom: 12,
     marginTop: 12}}
/>

If you are using flex, use it in all the components of parent View, else it is redundant with height: 200, width: 220.

Karl Taylor
  • 4,839
  • 3
  • 34
  • 62
5

Hey to make your image responsive is simple: here is an article i wrote about it. https://medium.com/@ashirazee/react-native-simple-responsive-images-for-all-screen-sizes-with-flex-69f8a96dbc6f

you can simply do this and it will scale

container: {
    width: 200,
    height: 220
  },// container holding your image 


  image: {
    width: '100%',
    height: '100%',
    resizeMode: cover,
  },
});

this is because the container which holds the image determines the height and width, so by using percentages you will be able to make your image responsive to all screens size.

here is another example:

<View style={{
width: 180,
height: 200,
aspectRatio: 1 * 1.4,
}}>
<Image
source={{uri : item.image.url}}
style={{
resizeMode: ‘cover’,
width: ‘100%’,
height: ‘100%’
}}
/>
</View>
Ali Shirazee
  • 1,008
  • 10
  • 11
5

To avoid the huge padding when resizing using 'contain', use 'stretch' with a height and an aspectRatio (that idea is from this answer).

{ height: '20%', aspectRatio: 1, resizeMode: 'stretch' }
Tamás Sengel
  • 55,884
  • 29
  • 169
  • 223
4

I tried other solutions and I didn't get the result I was looking for. This works for me.

<TouchableOpacity onPress={() => navigation.goBack()} style={{ flex: 1 }}>
        <Image style={{ height: undefined, width: undefined, flex: 1 }}
            source={{ uri: link }} resizeMode="contain"
        />
</TouchableOpacity>

Note I needed to set this as property of image tag than in css.

resizeMode="contain"

Also note that, you need to set flex: 1 on your parent container. For my component, TouchableOpacity is the root of the component.

Laurence
  • 7,633
  • 21
  • 78
  • 129
2
{ flex: 1, height: undefined, width: undefined, resizeMode: 'contain' }

If you are using these attributes in your style prop in the <Image /> and the image is disappeared.

Put your image into a <View> tag. Like this:

<View 
  style={{
      width: '100%',
     height: '30%'
     }}
>
          <Image
            source={require('../logo.png')}
            style={{
              flex: 1,
              height: undefined,
              width: undefined,
              resizeMode: 'contain'
            }}
            resizeMode={'cover'}
          />
</View>

Give your view the width and height you want.

Kamal Hossain
  • 530
  • 7
  • 18
2

add resizeMode="contain" in your tag.

<Image resizeMode="contain" />
1

Use Resizemode with 'cover' or 'contain' and set the height and with of the Image.

Pramod Mg
  • 2,316
  • 1
  • 11
  • 14
1

{ flex: 1, resizeMode: 'contain' } worked for me. I didn't need the aspectRatio

Moazzam Khan
  • 49
  • 1
  • 2
1

this worked for me

height: undefined,
width: undefined,
flex: 1,
resizeMode: "contain",

wrap the image in a View with flex:1

0

**After setting the width and the height of the image then use the resizeMode property by setting it to cover or contain.The following blocks of code translate from normal css to react-native StyleSheet

// In normal css
.image{
   width: 100px;
   height: 100px;
   object-fit: cover;
 }

// in react-native StyleSheet
image:{
   width: 100;
   height: 100;
   resizeMode: "cover";
 }

OR object-fit contain

// In normal css

.image{
   width: 100px;
   height: 100px;
   object-fit: contain;
 }

 // in react-native StyleSheet
image:{
   width: 100;
   height: 100;
   resizeMode: "contain";
 }
crispengari
  • 7,901
  • 7
  • 45
  • 53
0

**You can use like this **

<Image
    style={{
        height: 300,
        width: 300,
        resizeMode: "contain",
    }}
    source={require("../../assets/empty-cart.webp")}
    alt="empty-cart"
/>
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
Md Mahir
  • 81
  • 5
-1

I got the image Size and set it to max 130 width and 30 height.

const [imageSize, setImageSize] = useState();
Image.getSize(url, (width, height) => {
      setImageSize(logoSize(width, height));
});
...
<Image style={imageSize ?? initialSize} source={{uri: url}} />
...


const logoSize = (width, height) => {
  var maxWidth = 110;
  var maxHeight = 30;

  if (width >= height) {
    var ratio = maxWidth / width;
    var h = Math.ceil(ratio * height);

    if (h > maxHeight) {
      // Too tall, resize
      var ratio = maxHeight / height;
      var w = Math.ceil(ratio * width);
      var ret = {
        width: w,
        height: maxHeight,
      };
    } else {
      var ret = {
        width: maxWidth,
        height: h,
      };
    }
  } else {
    var ratio = maxHeight / height;
    var w = Math.ceil(ratio * width);

    if (w > maxWidth) {
      var ratio = maxWidth / width;
      var h = Math.ceil(ratio * height);
      var ret = {
        width: maxWidth,
        height: h,
      };
    } else {
      var ret = {
        width: w,
        height: maxHeight,
      };
    }
  }

  return ret;
};
-3

Here's my solution if you know the aspect ratio, which you can either get from the image metadata or prior knowledge. This fills the whole width of the screen, but that, of course, can be adjusted.

function imageStyle(aspect)
{
    //Include any other style requirements in your returned object.
    return {alignSelf: "stretch", aspectRatio: aspect, resizeMode: 'stretch'}
} 

This looks a bit nicer than contain, and takes less finessing with sizes, and it will adjust the height to maintain the proper aspect ratio so your images don't look skewed. Using contain will preserve the aspect ratio but will scale it to fit your other style requirements, which may drastically shrink the image.

Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
samdoj
  • 144
  • 8