Scaling Images with resizeMode in React Native

Learn how to scale images with resizeMode in React Native. Explore the different resizeMode property values in React Native and how to use them effectively in a project.

Imagine a website without images or illustrations — only plain text. It would be pretty unappealing and boring! Images make our applications and websites more appealing to the users, improve UX and SEO, and help us visually illustrate the points we are trying to pass across.

Using the right image and ensuring that it fits the viewport well will improve the website’s design and overall user experience. A distorted, overlapping, or poorly cropped image will only reduce the website’s design.

In this article, we will look at how to work with an image’s resizeMode in React Native and compare it to resizing images in CSS. 

Table of contents:

  • How to resize images in CSS
  • How to use image resizeMode in React Native
    • The cover property
    • The contain property
    • The stretch property
    • The repeat property
    • The center property
  • Building a React Native app to demonstrate resizeMode

Check out the full code in this GitHub repo. Then, let’s get started.


How to resize images in CSS

Before we begin looking into the resizeMode property in React Native, we should first look at how it works in CSS. Both cases cover the same basic concepts, so this will help us understand the topic in more detail.

You can also jump ahead in this article to start reading about resizeMode in React Native right away.

We will use the following stock image in our CSS image resizing demos:

Stock Image Of A Group Of Children Posing On A Beach

Look at the code below:

// App.js

import React from "react";
import "./styles.css";
export default function App() {
  return (
    <div className="App">
      <div className="image-container">
        <section>
          <h1>Image In Css</h1>
          <p> This is an article showing how image is resized in a website </p>
        </section>
      </div>
    </div>
  );
}

In the code above, we have a header and paragraph tag. We will be designing a hero section that has an image as a background and text on top of it. To add our image from our CSS file, copy the code below:

* {
  margin: 0;
  padding: 0;
}
.App {
  font-family: sans-serif;
}
.image-container {
  background-image: url("https://plus.unsplash.com/premium_photo-1664298270691-6aa217e5b1a5?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=870&q=80");
  height: 70vh;
}

The output of the code above will be the following:

Result Of Adding Stock Image With Css. Image Repeats To Fill Parent Div

We can see that the image is repeated. If we add a border to show the width and height of the parent div container, like so:

* {
  margin: 0;
  padding: 0;
}
.App {
  font-family: sans-serif;
}
.image-container {
  background-image: url("https://plus.unsplash.com/premium_photo-1664298270691-6aa217e5b1a5?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=870&q=80");
  height: 85vh;
  border: 2px solid black;
}

Then we will have something like this:

Adding Border Around Parent Div Css. Repeated Images Do Not Occupy Full Height Of Parent Container

In the image above, you will also notice that the height of the image is not occupying the full height of the parent container. This is because both have different dimensions and by extension different aspect ratios.

As a reminder, the aspect ratio of an element is the ratio between the height and width of the element. Simply put, it is the proportional relationship between the height and width of an image.

An aspect ratio is written with the width and the height separated by a colon. For example, an image that is 300 pixels wide and 300 pixels high has an aspect ratio of 1:1 — i.e., it has an equal number of pixels in width and height.

In CSS, you can use the aspect-ratio property to determine how your container or element will look. See the CSS below:

.image-container {
  background-image: url("https://plus.unsplash.com/premium_photo-1664298270691-6aa217e5b1a5?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=870&q=80");
  height: 85vh;
  border: 2px solid black;
  aspect-ratio: 1/1;
}

Adding a 1:1 aspect ratio to the container — in other words, giving the image’s parent container an equal width and height — will give the output below:

Setting Equal Parent Div Dimensions For One To One Ratio. Image Is Cut Off In Square Shape To Fit Parent Container

You can tweak the aspect ratio to see other results.

Now, back to our background image styling. We can make it look much better by adding a background-position and background-size property as well as removing the background-repeat property like below:

.image-container {
  background-image: url("https://plus.unsplash.com/premium_photo-1664298270691-6aa217e5b1a5?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=870&q=80");
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
  height: 85vh;
  border: 2px solid black;
}

The background-position moves the image either to the left, right, top, bottom, or center of the container. The background-size property has values like the center, cover, contain, and inherit.

The center value moves the image to the center while maintaining the image’s original aspect ratio. This might result in empty spaces around the image if the image’s aspect ratio or dimensions is smaller than that of the parent container:

Result Of Using Css Background Size Property With Center Value And Background Repeat Property With No Repeat Value. Image Is Centered With Original Aspect Ratio Without Filling Parent Container Completely, Leaving Empty Spaces Around Image

The contain value scales or enlarges the image to fill the parent container without stretching the image or cropping any part out. In this case, because we are setting the background-repeat property to no-repeat, the image will fit the height of the parent container but will leave empty spaces on the sides:

Result Of Using Css Background Size Property With Contain Value. Image Is Centered With Original Aspect Ratio Without Filling Parent Container Completely, Leaving Empty Spaces Around Image

The inherit value inherits the value of the parent container. This means that if the parent container has a value of contain, the image automatically takes that value. If the value of the parent container is cover, then the image’s value becomes cover. See the CSS below:

.App {
  font-family: sans-serif;
  background-size: cover;
}
.image-container {
  background-image: url("https://plus.unsplash.com/premium_photo-1664298270691-6aa217e5b1a5?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=870&q=80");
  background-position: center;
  background-repeat: no-repeat;
  background-size: inherit;
  height: 85vh;
  border: 2px solid black;
}

In this case, since the parent container doesn’t have a background-size value, the inherit value does nothing:

Result Of Using Css Background Size Property With Inherit Value For Image Container. Since Parent Container Has No Background Size Value, Inherit Value Does Nothing

The cover value fits the image into the parent container such that the image is enlarged to take the parent container’s aspect ratio. This will result in cropping out some portions of the image:

Result Of Using Css Background Size Property With Cover Value. Image Scales To Fit Into Parent Container While Maintaining Original Dimensions, Cropping Out Some Portions

Among the different values, we can see that the cover value gives us the closest output to what we want because it fills the whole parent width.

Let’s add a text overlay to finish our background image styling. First, we will reduce the brightness of the image so that our text can be visibly seen. To do so, we will add a background-color property, then a background-blend-mode property:

* {
  margin: 0;
  padding: 0;
}
.App {
  font-family: sans-serif;
  color: #fff;
}
h1 {
  font-size: 50px;
  text-align: center;
}
p {
  font-size: 24px;
  font-weight: 600;
}
.image-container {
  background-image: url("https://plus.unsplash.com/premium_photo-1664298270691-6aa217e5b1a5?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=870&q=80");
  background-color: rgba(36, 36, 36, 0.493);
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
  background-blend-mode: darken;
  border: 2px solid black;
  height: 85vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

The background-blend-mode property blends the image with the background-color. It has values like lighten, darken, luminosity, saturation, and so on.

In the code above, I used the RGBA color system so I can add some light opacity to the color. Then, I set the background-blend-mode value to darken to reduce the brightness of the background-image. The output of the code will be:

Same Image As In Previous Section, Now With Background Blend Mode Property With Darken Value And Text Overlay

Similarly, you can use the object-fit property to resize an image. Let us look at the JavaScript code below:

// App.js

import React from "react";
import "./styles.css";
export default function App() {
  return (
    <div className="App">
      <div className="image-container">
        <img
          src="https://plus.unsplash.com/premium_photo-1664298270691-6aa217e5b1a5?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=870&q=80"
          alt="boys"
        />
      </div>
    </div>
  );
}

Here’s the CSS code we’ll use for styling:

* {
  margin: 0;
  padding: 0;
}
.App {
  display: flex;
  justify-content: center;
  align-items: center;
  padding-top: 30px;
}
.image-container {
  border: 3px solid black;
  height: 85vh;
  aspect-ratio: 2/1;
}
img {
  width: 100%;
  height: 100%;
  object-fit: fill;
}

We gave our image container a height and then, using the aspect-ratio we learned about, we determined what we want our width to be. We also gave it a border to show the container’s width and height.

Next, using the object-fit property, you can give your image a value of contain, cover, fill, and so on. In this case, we gave it a value of fill, resulting in this output:

Alternate Css Approach Using Object Fit Property With Fill Value. Image Scales To Fit Parent Container Without Maintaining Original Dimensions, Resulting In Stretched Image

We have looked at how to handle image resizing in CSS on the web. Next, we will be looking at how to resize images in React Native.

How to use image resizeMode in React Native

Note that there is more than one way to resize images in React Native. We can either resize the image in the CSS style as we have seen above, or we can resize it directly in the image component.

The image component in React Native provides a resizeMode option that we can use to resize our images directly. The code snippet looks like this:

<Image source={image_source} resizeMode="repeat" />

In React Native, the resizeMode property has five values — cover, contain, stretch, repeat, and center. These values help us to resize our images when the frame doesn’t match or fit the raw image dimensions.

The cover, contain, and center values for resizeMode behave similarly to their background-size counterparts in CSS, which makes them easy to understand.

We will use the following stock image as we explore each resizeMode property value in React Native:

Stock Image Of Brown Dog With Red Collar

Let’s dive into the five resizeMode property values now.

The cover property

The default resizeMode property in React Native is cover. Like background-property: cover in CSS, this property resizes images by an equal factor in both dimensions so that the image maintains its original proportions and is not stretched or distorted when resized.

Using cover means that the image fills the entire container of the parent view. However, this property may result in parts of the image being cropped out if the aspect ratio of the view does not match the aspect ratio of the image.

A good use case for this property would be to display image backgrounds where we want the image to occupy and fill the entire container, as we did in the above example. However, with this property, you’ll want to ensure that the image you select will look fine when cropped to fill the view.

Let’s look at the following example:

// App.js

import React from 'react';
import {View, Image, StyleSheet, Dimensions, SafeAreaView} from 'react-native';
import Img2 from '../assets/image2.jpg';
export default function Home({navigation}) {
  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.imageContainer}>
        <Image source={Img2} style={styles.image} />
      </View>
    </SafeAreaView>
  );
}
const windowWidth = Dimensions.get('window').width;
const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexWrap: 'wrap',
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
  },
  imageContainer: {
    height: 400,
    width: windowWidth - 20,
    borderWidth: 2,
    borderColor: '#000',
  },
  image: {
    flex: 1,
    resizeMode: 'cover',
    width: '100%',
  },
});

The code above would give us the result below:

Stock Image Of Brown Dog In Red Collar Inserted Into Demo React Native Project To Prepare For Resizemode Tutorial

As you can see, the image completely fills the parent view, which is indicated by the black border. However, if you compare this to the original image, you can see that some areas have been cropped out.

The contain property

The contain property resizes the image’s height and width so that the image fits the parent container while maintaining the image’s original aspect ratio. This is similar to background-property: contain in CSS and results in an image that is fully visible within the view.

This means just like in CSS, if the view’s aspect ratio does not match the aspect ratio of the image — i.e., the image’s aspect ratio is less than the view’s aspect ratio — using the <code<contain property to scale your image will result in empty spaces being left around the image.

Look at the example below:

// App.js

import React from 'react';
import {View, Image, StyleSheet, Dimensions, SafeAreaView} from 'react-native';
import Img2 from '../assets/image2.jpg';
export default function Home({navigation}) {
  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.imageContainer}>
        <Image source={Img2} style={styles.image} />
      </View>
    </SafeAreaView>
  );
}
const windowWidth = Dimensions.get('window').width;
const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexWrap: 'wrap',
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
  },
  imageContainer: {
    height: 400,
    width: windowWidth - 20,
    borderWidth: 2,
    borderColor: '#000',
  },
  image: {
    flex: 1,
    resizeMode: 'contain',
    width: '100%',
  },
});

In the code above, the aspect ratio of the image does not match the aspect ratio of the view, resulting in the following:

Stock Image Of Brown Dog In Red Collar Scaled Using React Native Resizemode With Contain Property, Resulting In Image Scaled To Display Fully Within Parent Container With Empty Spaces On Sides

You can see that the image fits into the view but leaves some empty spaces on the sides. An example use case of this property could be for displaying user profile pictures where you want the entire image to fit into the container and still be visible.

The stretch property

The stretch property stretches the image to fill the entire view container. This may result in a distorted or stretched image if the aspect ratios for the image and view do not match. Let’s see this in action:

// App.js

import React from 'react';
import {View, Image, StyleSheet, Dimensions, SafeAreaView} from 'react-native';
import Img2 from '../assets/image2.jpg';
export default function Home({navigation}) {
  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.imageContainer}>
        <Image source={Img2} style={styles.image} />
      </View>
    </SafeAreaView>
  );
}
const windowWidth = Dimensions.get('window').width;
const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexWrap: 'wrap',
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
  },
  imageContainer: {
    height: 400,
    width: windowWidth - 20,
    borderWidth: 2,
    borderColor: '#000',
  },
  image: {
    flex: 1,
    resizeMode: 'stretch',
    width: '100%',
  },
});

The code above will result in the following:

Stock Image Of Brown Dog In Red Collar Scaled Using React Native Resizemode With Stretch Property, Resulting In Image Scaled To Fill Parent Container Completely By Changing Image Dimensions. Image Appears Stretched And Flattened

As you can see, although the image completely fills the view, it doesn’t look like the original image. This is another useful property for background images that you want to fill the entire container, but may not be ideal if your image and container aspect ratios do not match closely.

The repeat property

The repeat property repeats the image to fill the view container while maintaining the image’s original aspect ratio. In other words, if there are empty spaces because the view’s aspect ratio is bigger, it then repeats the image to fill up the spaces.

Look at the example below:

// App.js

import React from 'react';
import {View, Image, StyleSheet, Dimensions, SafeAreaView} from 'react-native';
import Img2 from '../assets/image2.jpg';
export default function Home({navigation}) {
  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.imageContainer}>
        <Image source={Img2} style={styles.image} />
      </View>
    </SafeAreaView>
  );
}
const windowWidth = Dimensions.get('window').width;
const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexWrap: 'wrap',
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
  },
  imageContainer: {
    height: 400,
    width: windowWidth - 20,
    borderWidth: 2,
    borderColor: '#000',
  },
  image: {
    flex: 1,
    resizeMode: 'repeat',
    width: '100%',
  },
});

Here’s the result of the code above:

Stock Image Of Brown Dog In Red Collar Scaled Using React Native Resizemode With Repeat Property. Image Repeats Using Original Dimensions To Fill Parent Container While Displaying Full Image At Least Once

Repeating images as shown above can be useful if you want to have image patterns or a tile design. However, if you’re not careful about how you use this, it can end up looking sloppy or cluttered to your user.

The center property

Like background-size: center in CSS, the center property in resizeMode moves the image to the center of the view container.

If the image’s aspect ratio is smaller than the aspect ratio of the view, it will result in empty spaces around the image. On the other hand, if the image’s aspect ratio is bigger than that of the view, the image is shrunk or reduced to fit the view.

This can be useful for displaying user profile avatars and logos. That is because you want the avatar or logo to always be at the center of the parent container, without minding the aspect ratio.

See the example below:

// App.js

import React from 'react';
import {View, Image, StyleSheet, Dimensions, SafeAreaView} from 'react-native';
import Img2 from '../assets/image2.jpg';
export default function Home({navigation}) {
  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.imageContainer}>
        <Image source={Img2} style={styles.image} />
      </View>
    </SafeAreaView>
  );
}
const windowWidth = Dimensions.get('window').width;
const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexWrap: 'wrap',
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
  },
  imageContainer: {
    height: 400,
    width: windowWidth - 20,
    borderWidth: 2,
    borderColor: '#000',
  },
  image: {
    flex: 1,
    resizeMode: 'center',
    width: '100%',
  },
});

Our output would look like so:

Stock Image Of Brown Dog In Red Collar Scaled Using React Native Resizemode With Center Property. Image Is Displayed Fully In Center Of Parent Container With Blank Spaces On Sides

Building a React Native app to demonstrate image resizeMode

Let’s build a sample app to see how the different image resizeMode values work. This will help demonstrate our lesson in a practical and visual way for better understanding. Spin up your React Native app using your preferred method — I prefer using Expo — and let’s continue.

In your App.js file, copy the following code. There’s a lot here, but don’t worry! I will explain below:

// App.js

import React, {useState} from 'react';
import {
  View,
  Text,
  Image,
  StyleSheet,
  Dimensions,
  SafeAreaView,
  TouchableOpacity,
} from 'react-native';
import Img2 from '../assets/image2.jpg';

export default function Home({navigation}) {
  const [state, setState] = useState('contain');

  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.imageContainer}>
        <Image source={Img2} style={styles.image} resizeMode={state} />
      </View>

      <View style={styles.buttonWrapper}>
        <TouchableOpacity
          style={state === 'cover' ? styles.activeButton : styles.button}
          onPress={() => setState('cover')}>
          <Text style={styles.buttonText}>Cover</Text>
        </TouchableOpacity>
        <TouchableOpacity
          style={state === 'contain' ? styles.activeButton : styles.button}
          onPress={() => setState('contain')}>
          <Text style={styles.buttonText}>Contain</Text>
        </TouchableOpacity>
        <TouchableOpacity
          style={state === 'repeat' ? styles.activeButton : styles.button}
          onPress={() => setState('repeat')}>
          <Text style={styles.buttonText}>Repeat</Text>
        </TouchableOpacity>
        <TouchableOpacity
          style={state === 'stretch' ? styles.activeButton : styles.button}
          onPress={() => setState('stretch')}>
          <Text style={styles.buttonText}>Stretch</Text>
        </TouchableOpacity>
        <TouchableOpacity
          style={state === 'center' ? styles.activeButton : styles.button}
          onPress={() => setState('center')}>
          <Text style={styles.buttonText}>Center</Text>
        </TouchableOpacity>
      </View>
    </SafeAreaView>
  );
}
const windowWidth = Dimensions.get('window').width;
const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexWrap: 'wrap',
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
  },
  imageContainer: {
    height: 400,
    width: windowWidth - 20,
    borderWidth: 2,
    borderColor: '#000',
  },
  image: {
    flex: 1,
    width: '100%',
  },
  buttonWrapper: {
    flexDirection: 'row',
    width: windowWidth - 20,
    marginTop: 20,
    justifyContent: 'space-between',
    flexWrap: 'wrap',
  },
  activeButton: {
    backgroundColor: 'green',
    paddingVertical: 5,
    paddingHorizontal: 20,
    borderRadius: 5,
    marginBottom: 10,
  },
  button: {
    backgroundColor: 'grey',
    paddingVertical: 5,
    paddingHorizontal: 20,
    borderRadius: 5,
    marginBottom: 10,
  },
  buttonText: {
    fontSize: 20,
    fontWeight: '600',
  },
});

We have an image that we want to resize to fit our view container.

We also have five buttons, each representing the five resizeMode values. When we click each button, we are setting the associated value — contain, cover, repeat, stretch, and center — as the current value of our state.

Finally, when a button is clicked, we change the color of the button to green to show that it has been clicked and that the image is now resized to the indicated resizeMode value. The final application looks like this:

Stock Image Of Brown Dog In Red Collar Displayed Above Five Buttons Labeled With Each React Native Resizemode Property. User Shown Clicking On Each Button As Image Scales To Demonstrate Each Property In Action

Conclusion

In this article, we explored the different resizeMode property values in React Native and how to use them. We also saw how to resize images using CSS for the web, as well as what images will look like when using these properties.

When building React Native applications, we have to understand these image resizeMode property values — along with the aspect ratios for our image and view — so that we can scale our images better and improve the visual design and user experience.

Source: https://blog.logrocket.com

#reactnative 

Scaling Images with resizeMode in React Native
3.45 GEEK