Create a Responsive React Image Component

Ifeoma Imoh

Images are an important part of the web, so delivering the right image for the right device at the right time while maintaining optimized quality is very important.

In this Jam, We will go over a few techniques using the Cloudinary-React SDK v2 and JavaScript SDK v2, which are currently in BETA, to see how we can apply various transformations to our images. Without further ado, let's dive in.

Here is a link to the demo on CodeSandbox.

Create A Cloudinary Account

If you don't have a Cloudinary account yet, you can sign up for a free account. Log in after creating your account, and on your dashboard page, you should see all your credentials (cloud name, etc.) We are only interested in the cloud name since that's what we will need in our React application.

Set up Your Project

Open your terminal and run the following command to bootstrap a React app with CRA (create-react-app) template in a folder called my-project.

1npx create-react-app my-project

The next step is to install the dependencies that we will need in this project. Run the following command to install them.

1npm install @cloudinary/url-gen @cloudinary/react --save

We're installing the Cloudinary SDKs we'll be using in our React application. The @Cloudinary/url-gen package is used to configure Cloudinary, create delivery URLs for our images, and apply transformations. The transformed images will be passed as an input to the component provided by the @cloudinary/react package, which will render the media on our site.

Transforming Assets

Cloudinary provides us with different methods to apply transformations to our assets. We'll be using the URL of some random remote image on the web.

Open your App.js file and add the following to it.

1import { Cloudinary } from "@cloudinary/url-gen";
2 import { AdvancedImage } from "@cloudinary/react";
3 import { fill } from "@cloudinary/url-gen/actions/resize";
4 import { Effect } from "@cloudinary/url-gen/actions/effect";
5 import { byRadius } from "@cloudinary/url-gen/actions/roundCorners";
6 import { byAngle } from "@cloudinary/url-gen/actions/rotate";
7 const cld = new Cloudinary({
8 cloud: {
9 cloudName: "ifeomaimoh"
10 }
11 });
12 const App = () => {
13 const file =
14 "https://images.pexels.com/photos/2246476/pexels-photo-2246476.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940";
15 let image = cld.image(file);
16 image = image.setDeliveryType("fetch");
17 image = image
18 .effect(Effect.sepia())
19 .resize(fill().height(500).width(490))
20 .roundCorners(byRadius().radius(40))
21 .rotate(byAngle(20));
22
23 // This gives the full delivery URL of the tranformations applied above.
24 console.log({ url: image.toURL() });
25
26 return (
27 <div style={{ padding: "5rem" }}>
28 <h1 style={{ marginBottom: "50rem" }}>scroll to lazy load </h1>
29 <AdvancedImage cldImg={image} />
30 </div>
31 );
32 };
33 export default App;

In the code snippet above, we're importing the Cloudinary class, the AdvancedImage React component, and some qualifiers that we would use to build and transform our image URL. We start by configuring our Cloudinary instance with our cloud name. Inside the App component, we define and store the URL of a remote image in a variable called file, then we instantiate a CloudinaryImage object and pass the variable to it.

We are also specifying how we want our image to be delivered. We're setting the delivery type to fetch for our remote image by calling the setDeliveryType method. We're also transforming our image using the transformation actions and qualifiers on the CloudinaryImage object. We applied the sepia effect to the image, resized it, added rounded corners, and rotated it.

https://res.cloudinary.com/<cloud_name>/image/<delivery type>/<transformations>/<file>

From the format above, we can see where transformation parameters live.

The order in which you write transformations is important to get the desired effects.

Finally, we pass the transformed image object to the cldImg attribute in the AdvancedImage component, which renders the image on our site. Open your terminal and start your application to see the transformed image.

Under the hood, the AdvancedImage component fetches the image from the webserver where it is located and then applies the transformations we specified.

Optimizing Images

There are plugins provided by the Cloudinary React library that help optimize the way you render media on your site. Let's check out three of them, but I'd like us first to look at the quality transformation parameter.

Quality Optimization The quality transformation parameter enables us to choose the quality compression level for our images, with values ranging from 1 to 100. The lower the quality value, the more the file is compressed to smaller file size.

Let's update our App.js file to include the following:

1image = image
2 ...
3 ...
4 .rotate(byAngle(20))
5 .quality ('q_40');

We added the quality transformation parameter q_40 and specified that we wanted an image quality of 40. The result of this is a compressed image with small size and good quality. For most images, specifying an optimal value is difficult If we seek to optimize our images while maintaining quality. Cloudinary also provides us with a quality transformation parameter auto, which delivers an image with an automatically determined level of quality. You can also set the default image quality level in the Upload Settings for your account.

Below is the result of applying different quality values.

Other variants of the auto parameter include q_auto:low, q:auto:best, etc., each with different compression levels. See here for more options.

Lazy Loading Images This ensures that images are delayed and loaded only when they are visible in the viewport. Add the following plugins to the list of your imports.

1import {Cloudinary} from '@cloudinary/url-gen';
2 import {
3 AdvancedImage,
4 lazyload,
5 responsive,
6 placeholder,
7 } from '@cloudinary/react';

Let's now update our App component to include the plugins we imported.

1const App = () =>{
2 const image = ...
3 ....
4 return (
5 <div style={{paddingBottom: '30rem'}}>
6 <h1>scroll to lazy load </h1>
7 <p style={{marginBottom: '50rem'}} />
8 <AdvancedImage
9 cldImg={image}
10 plugins={[lazyload ('0', 1), placeholder ('blur')]}
11 />
12 </div>
13 );
14 }

In the code snippet above, we use the lazyload and placeholder plugin in the AdvancedImage component. The lazyload plugin uses the intersection observer API under the hood to detect if a user scrolls near the image or iframe before loading it. We are saying we want our image loaded when it is 100% visible on the page. Lazy loading images helps conserve bandwidth for images that are not seen and reduce the time needed to load a page.

We use the placeholder plugin to render a fallback image while the image is being loaded. The placeholder image loads quickly, and your page content won't jump around. Because we are specified "blur" as our placeholder option, we will get a blurred version of the target image while waiting for the full quality image to be downloaded.

Responsive Images Initially, we resized our image using the resize qualifier. Although this works, the dimension of the image will remain static as the viewport size changes. Cloudinary React library provides the responsive() plugin that we can use to resize our image based on the viewport size automatically.

First, we need to remove the resize qualifier.

1// Remove this line of code.
2 .resize(fill().height(500).width(490))

Let's include the responsive plugin in our App component.

1plugins={[lazyload ('0', 1),responsive(200),placeholder ('blur')]}

The order of the plugins is important to ensure that everything works correctly.

The responsive plugin function accepts either a single value (step) or an array of values. In our case, we passed in a single value - 200 pixels. Each time the viewport size increases or decreases by that value, a new image will be loaded.

Find the source code here on Github.

Conclusion

In this post, we explored how to use some of the advanced features of the Cloudinary-React SDK and JavaScript SDK to build and apply various transformations to our image component. You can find more information about the Cloudinary React SDK v2 and plugins here.

Some Resources You May Find Useful

Ifeoma Imoh

Software Developer

Ifeoma is a software developer and technical content creator in love with all things JavaScript.