How to set image width to be 100% and height to be auto in react native?

JavascriptImageReactjsReact Native

Javascript Problem Overview


I am trying to display list of images in a scrollview. Width should be 100%, while height should be automatic, keeping aspect ratio.

The searches I did pointed to various solutions which give fullscreen background style.

const styles = StyleSheet.create({
    image: {
        width: null,
        height: 300,
        resizeMode: 'cover'
    }
});

<ScrollView style={{flex: 1}}>
    <Image style={styles.image} source={require('../../../images/collection-imag1.png')}/>
    <Image style={styles.image} source={require('../../../images/collection-imag2.png')}/>
</ScrollView>

I have tried various combinations of width: null, height: null, flex: 1, alignSelf etc. The above solution is almost working, except the height is not dynamic. Parts of the image are not visible.

Javascript Solutions


Solution 1 - Javascript

So after thinking for a while I was able to achieve height: auto in react-native image. You need to know the dimensions of your image for this hack to work. Just open your image in any image viewer and you will get the dimensions of the your image in file information. For reference the size of image I used is 541 x 362

First import Dimensions from react-native

import { Dimensions } from 'react-native';

then you have to get the dimensions of the window

const win = Dimensions.get('window');

Now calculate ratio as

const ratio = win.width/541; //541 is actual image width

now the add style to your image as

imageStyle: {
    width: win.width,
    height: 362 * ratio, //362 is actual height of image
}

Solution 2 - Javascript

"resizeMode" isn't style property. Should move to Image component's Props like below code.

const win = Dimensions.get('window');

const styles = StyleSheet.create({
    image: {
        flex: 1,
        alignSelf: 'stretch',
        width: win.width,
        height: win.height,
    }
});

...
    <Image 
       style={styles.image}
       resizeMode={'contain'}   /* <= changed  */
       source={require('../../../images/collection-imag2.png')} /> 
...

Image's height won't become automatically because Image component is required both width and height in style props. So you can calculate by using getSize() method for remote images like this answer and you can also calculate image ratio for static images like this answer.

There are a lot of useful open source libraries -

Solution 3 - Javascript

I've found a solution for width: "100%", height: "auto" if you know the aspectRatio (width / height) of the image.

Here's the code:

import { Image, StyleSheet, View } from 'react-native';

const image = () => (
	<View style={styles.imgContainer}>
		<Image style={styles.image} source={require('assets/images/image.png')} />
	</View>
);

const style = StyleSheet.create({
	imgContainer: {
		flexDirection: 'row'
	},
	image: {
		resizeMode: 'contain',
		flex: 1,
		aspectRatio: 1 // Your aspect ratio
	}
});

This is the most simplest way I could get it to work without using onLayout or Dimension calculations. You can even wrap it in a simple reusable component if needed. Give it a shot if anyone is looking for a simple implementation.

Solution 4 - Javascript

use aspectRatio property in style

Aspect ratio control the size of the undefined dimension of a node. Aspect ratio is a non-standard property only available in react native and not CSS.

  • On a node with a set width/height aspect ratio control the size of the unset dimension
  • On a node with a set flex basis aspect ratio controls the size of the node in the cross axis if unset
  • On a node with a measure function aspect ratio works as though the measure function measures the flex basis
  • On a node with flex grow/shrink aspect ratio controls the size of the node in the cross axis if unset
  • Aspect ratio takes min/max dimensions into account

docs: https://reactnative.dev/docs/layout-props#aspectratio

try like this:

import {Image, Dimensions} from 'react-native';

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

<Image
    source={{
        uri: '<IMAGE_URI>'
    }}
    style={{
        width: width * .2,  //its same to '20%' of device width
        aspectRatio: 1, // <-- this
        resizeMode: 'contain', //optional
    }}
/>

Solution 5 - Javascript

I had problems with all above solutions. Finally i used aspectRatio to do the trick. When you know image width and height and they are large, just calculate aspectRatio and add it to image like:

<PhotoImage
    source={{uri: `data:image/jpeg;base64,${image.base64}`}}
    style={{ aspectRatio: image.width / image.height }}
 />

AspectRatio is a layout property of React Native, to keep aspect ratio of image and fit into parent container: https://facebook.github.io/react-native/docs/layout-props#aspectratio

Solution 6 - Javascript

You always have to set the width and height of an Image. It is not going to automatically size things for you. The React Native docs says so.

You should measure the total height of the ScrollView using onLayout and set the height of the Images based on it. If you use resizeMode of cover it will keep the aspect ratio of your Images but it will obviously crop them if it's bigger than the container.

Solution 7 - Javascript

Solution April 2020:

So the above answers are cute but they all have (imo) a big flaw: they are calculating the height of the image, based on the width of the user's device.

To have a truly responsive (i.e. width: 100%, height: auto) implementation, what you really want to be doing, is calculating the height of the image, based on the width of the parent container.

Luckily for us, React Native provides us with a way to get the parent container width, thanks to the onLayout View method.

So all we need to do is create a View with width: "100%", then use onLayout to get the width of that view (i.e. the container width), then use that container width to calculate the height of our image appropriately.

 

Just show me the code...

The below solution could be improved upon further, by using RN's Image.getSize, to grab the image dimensions within the ResponsiveImage component itself.

JavaScript:

// ResponsiveImage.ts

import React, { useMemo, useState } from "react";
import { Image, StyleSheet, View } from "react-native";

const ResponsiveImage = props => {
  const [containerWidth, setContainerWidth] = useState(0);
  const _onViewLayoutChange = event => {
    const { width } = event.nativeEvent.layout;
    setContainerWidth(width);
  }

  const imageStyles = useMemo(() => {
    const ratio = containerWidth / props.srcWidth;
    return {
      width: containerWidth,
      height: props.srcHeight * ratio
    };
  }, [containerWidth]);

  return (
    <View style={styles.container} onLayout={_onViewLayoutChange}>
      <Image source={props.src} style={imageStyles} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: { width: "100%" }
});

export default ResponsiveImage;


// Example usage...

import ResponsiveImage from "../components/ResponsiveImage";

...

<ResponsiveImage
  src={require("./images/your-image.jpg")}
  srcWidth={910} // replace with your image width
  srcHeight={628} // replace with your image height
/>

 

TypeScript:

// ResponsiveImage.ts

import React, { useMemo, useState } from "react";
import {
  Image,
  ImageSourcePropType,
  LayoutChangeEvent,
  StyleSheet,
  View
} from "react-native";

interface ResponsiveImageProps {
  src: ImageSourcePropType;
  srcWidth: number;
  srcHeight: number;
}

const ResponsiveImage: React.FC<ResponsiveImageProps> = props => {
  const [containerWidth, setContainerWidth] = useState<number>(0);
  const _onViewLayoutChange = (event: LayoutChangeEvent) => {
    const { width } = event.nativeEvent.layout;
    setContainerWidth(width);
  }

  const imageStyles = useMemo(() => {
    const ratio = containerWidth / props.srcWidth;
    return {
      width: containerWidth,
      height: props.srcHeight * ratio
    };
  }, [containerWidth]);

  return (
    <View style={styles.container} onLayout={_onViewLayoutChange}>
      <Image source={props.src} style={imageStyles} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: { width: "100%" }
});

export default ResponsiveImage;


// Example usage...

import ResponsiveImage from "../components/ResponsiveImage";

...

<ResponsiveImage
  src={require("./images/your-image.jpg")}
  srcWidth={910} // replace with your image width
  srcHeight={628} // replace with your image height
/>

Solution 8 - Javascript

Right click on you image to get resolution. In my case 1233 x 882

const { width } = Dimensions.get('window');

const ratio = 882 / 1233;

    const style = {
      width,
      height: width * ratio
    }

<Image source={image} style={style} resizeMode="contain" />

That all

Solution 9 - Javascript

For image tag you can use this type of style, it worked for me:

imageStyle: {
    width: Dimensions.get('window').width - 23,
    resizeMode: "contain",
    height: 211,
 },

Solution 10 - Javascript

Let me share what I end up with, which allows to set correctly width or height by getting the image dimensions. In addition, the code allows to fetch a loading image while the large image data we need is being transfered:

  1. Use static method Image.prefetch to have the image downloaded and available to cache.

  2. Use static method Image.getSize to collect height and width and use it to compute an aspect ratio and then the final height (or width)

  3. Display image with a default style to your prefered width (The height will be computed with aspect ratio kept)

     function ImageX(props: {source: string, id: string})
     {
       const [imageHeight, setImageHeight] = React.useState(1);
       Image.prefetch(props.source)
       .then(() => {
           Image.getSize(props.source, (width, height) => {
             let aspectRatio =  height/width;
             setImageHeight(aspectRatio*Dimensions.get('window').width);
           });
       })
       .catch(error => console.log(error))
       if (imageHeight <=1) //Image not in cache (disk) yet
         {
           return (
             <Image key={props.id} style={styleimg.image} source={{uri: 'http://www.dsdsd/loaderpreview.gif'}}/>
           );
       }
       else
       {
         return (
           <Image key={props.id} style={styleimg.image} height={imageHeight} source={{uri: props.source}}/>
         );
       }
     }
    

    const styleimg = StyleSheet.create({ image: { width: Dimensions.get('window').width, resizeMode: 'contain' //... // you can set a height defaults } });

Solution 11 - Javascript

this may help for auto adjusting the image height having image 100% width

image: { width: "100%", resizeMode: "center" "contain", height: undefined, aspectRatio: 1, }

Solution 12 - Javascript

function ImageX( props){
   const [state, setState] = React.useState({v:{height:1}});
   useEffect(() => {
    if(!props.source || !props.source.uri) return;
    Image.prefetch(props.source.uri)
    .then(() => {
        Image.getSize(props.source.uri, (width, height) => {
          let aspectRatio =  height/width;
          state.v.width=Dimensions.get('window').width;
          state.v.height=aspectRatio*state.v.width;
          setState({...state});
        });
    })
    .catch(error => console.log(error))
   },[props.source && props.source.uri]);
   
   if (state.v.height <=1) //Image not in cache (disk) yet
     {
      return (
        <Image {...props}/>
      );
   }
   else
   {
     let neededst={v:{width:state.v.width, height:state.v.height}}
     let st={v:props.style};
    assignObject(neededst, st);
     return (
       <Image {...props} style={neededst.v}/>
     );
   }
 }

 function assignObject(target, source) {
  if (!source) return;
  for (let k in target) {
    let v = target[k];
    if (Object(v) === Object) assignObject(v, source[k]);
    else {
      if (source[k]) {
        try {
          Object.assign(v, source[k]);
        } catch (e) {
          alert(e);
        }
      }
    }
  }

  for (let k in source) {
    if (!target[k]) {
      target[k] = source[k];
    }
  }

}

Using Image component from https://reactnativeelements.com/docs/image

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPrabhakar BhatView Question on Stackoverflow
Solution 1 - JavascriptVinit KadamView Answer on Stackoverflow
Solution 2 - JavascriptlwinkyawmyatView Answer on Stackoverflow
Solution 3 - JavascriptArafat ZahanView Answer on Stackoverflow
Solution 4 - JavascriptTofa Maulana IrvanView Answer on Stackoverflow
Solution 5 - JavascriptŁukasz BlaszyńskiView Answer on Stackoverflow
Solution 6 - JavascriptrclaiView Answer on Stackoverflow
Solution 7 - JavascriptJon James DesignsView Answer on Stackoverflow
Solution 8 - JavascriptDmitry PreeternalView Answer on Stackoverflow
Solution 9 - Javascriptkallayya HiremathView Answer on Stackoverflow
Solution 10 - JavascriptThomas BonesView Answer on Stackoverflow
Solution 11 - Javascriptsumukha hegdeView Answer on Stackoverflow
Solution 12 - JavascriptTarasantanView Answer on Stackoverflow