npm i Supports features like Custom Image Placeholder/Loader Component, srcset, lazy Loading, Graceful Loading, Progressive Image Loading.Use of Intersection Observer and navigator.onLine (Better performance and Optimization) react-progressive-graceful-image Motivation I was working on an e-commerce PWA and you know what is there on an e-commerce platform? Images, more images and well, a lot more images. The truth is, with the increase in internet speed, images are everywhere now, be it e-commerce/social media/blog/news/dating or any other site. Image is Everything, Everything is Image — (Credit: Rockstar movie) So what’s the big deal in loading images? Just make an tag and done!! I am sure you are thinking it’s not even that easy. <img src=path-to-image /> The problem is loading of an image takes time. Particularly, when there is a huge number of high-quality images on a single page. Solutions To give a better user experience, various things can be done: Image Placeholder — Keep a static image(png/svg) / a loader(gif) / a colored background div(usually grey) / a grey div with shimmer effect like the one below, until the real image is downloaded. (Image Loading with Shimmer effect animated placeholder) — Use Progressive JPEG instead of a normal Baseline JPEG image, although it’s not much in the control of client-side code. Here is an example. Progressive JPEG Baseline Image vs Progressive Image LoadingLazy Loading — Don’t load an image until it is visible or close to the viewport. Below gif explains it. (Lazy loading) — Display the placeholder until the image is fully loaded and retry image loading even if network error happens(mostly when a device switches network for some reason like power/network failure). Graceful Loading — Sites like medium, facebook, etc uses a tiny version of the real image with blur filter until the real image is downloaded and then uses some CSS transition to replace the tiny one. Here is an example. Progressive Image Loading (Progressive Image Loading) srcset attribute —used to let the browser automatically choose image based on device screen size and/or device pixel ratio(DPR). Huh? That’s a lot of information and so many things can be done. Now to build an <Image/> component in ReactJS with one or two of the above features is easy, but how about building an <Image/> component with all of the above features? Drumroll, please!! Enter the savior, the superhero npm package… npm i react-progressive-graceful-image Some FAQs Why do we need various combinations together, why not implement just one variation, for example - Progressive Image Loading? — Let’s take an example. Home Page of an e-commerce has various sections, some with ads for which tiny images might be available. Since it’s a landing page that gets maximum eyeballs of visitors, hence better user experience is required. But “Search result page” or “Product description page” may serve images for which tiny images are not available(why you ask? One of the reasons, it’s costly). So we need let’s say, a grey div placeholder with shimmer effect. And as a developer, you don’t want to make multiple components for images. Similarly, there can be other use-cases. You get my point. Why do we use this npm package? Is there any other better package? — I found some really good packages like , , and but honestly speaking, most of them lacked one or more important features. react-shimmer react-graceful-image react-progressive-image Like, lacked shimmer effect and lacked lazy-loading and graceful-loading. In fact, I started by forking and adding new features from . Later, I improved upon them. react-graceful-image react-progressive-image react-progressive-image react-graceful-image What about performance, optimization, and browser support? — Currently, the package size is . I have used Intersection Observer for Lazy Loading (Better Performance) as compared to throttling scroll event listeners which run on the main thread. 3.6kb One big reason, Intersection Observer runs on a separate thread in the Browser. Read more about it and see it in action at which is the only dependency of this package. here @researchgate/react-intersection-observer Also, the retry strategy for graceful loading in was not quite optimized. It would also hang the screen sometimes when the device goes offline and a lot of image requests are sent simultaneously which would fail anyway. So I have used based strategy for optimization. react-graceful-image navigator.onLine In case Intersection Observer is not supported by a browser, its polyfill is available . here Usage Great!! How do I use it? Any demo? Here you go… CodeSandbox You can find more examples and documentation on or . npm github In case you find any issues or improvements, PRs and contributions are welcome on github. Always use padding-percentage solution to wrap your custom <Image/> component to prevent any reflow and improve browser performance as explained in this . Extra Browny Stuff: article to make the best use of this logic with this npm package. Here is a small code snippet React ; ProgressiveImage ; styled ; PlcHolder = styled.img ; ImageParent = styled.div ; StyledImage = styled.img ; ({ width = , height = , srcSetData, src, placeholder, alt = , }) => { ( <ProgressiveImage srcSetData={{ srcSet: srcSetData.srcSet, srcSet: srcSetData.sizes, }} src={src} placeholder={placeholder} > {(src, loading, srcSetData) => { return !placeholder ? ( loading ? ( <PlcHolder src="data:image/svg+xml;charset=utf-8,%3Csvg xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg' width%3D'200' height%3D'150' viewBox%3D'0 0 200 150'%2F%3E" w={width} h={height} /> ) : ( <StyledImage srcSet={srcSetData.srcSet} sizes={srcSetData.sizes} src={src} alt={alt} /> ) ) : ( <StyledImage srcSet={srcSetData.srcSet} style={{ filter: loading ? 'blur(15px)' : 'blur(0px)' }} sizes={srcSetData.sizes} src={src} alt={alt} /> ); }} </ProgressiveImage> </ImageParent> ); }; import from 'react' import from 'react-progressive-graceful-image' import from 'styled-components' const ` background: linear-gradient( to right, rgb(246, 247, 248) 0%, rgb(237, 238, 241) 20%, rgb(246, 247, 248) 40%, rgb(246, 247, 248) 100% ); @keyframes placeHolderShimmer { 0% { background-position: top right; } 100% { background-position: top left; } } top: 0; left: 0; bottom: 0; right: 0; width: 100%; height: 100%; max-width: 100%; max-height: 100%; position: absolute; background-size: 2250px 2250px !important; background-repeat: no-repeat !important; background-position: 0 0 !important; animation: placeHolderShimmer 1.5s ease-in-out infinite; ` const ` position: relative; width: 100%; ` const ` top: 0; left: 0; bottom: 0; right: 0; width: 100%; height: 100%; max-width: 100%; max-height: 100%; position: absolute; ` export default 414 184 'Image' return < = ( / ) * + '%', }} > ImageParent style {{ paddingBottom: height width 100 Thank you for reading this article. Please share and clap if you liked it. Let me know in the comments below if you want me to give more details about the code implementation of this npm package, as some have asked me personally.