Improve your web apps UX by enhancing image render with React's onLoad
event and simple SCSS.
This article is cross-posted on Codebrahma and Medium
Let's cut to the chase. The GIF below shows what we are going to achieve by the end of this post.
Here is the Completed Component - RenderSmoothImage
.
I have published this as an npm
package render-smooth-image-react. The source code is available on GitHub.
Little Back Story
I recently started working on a media-heavy app. Everything was cool until I noticed a bunch of images rendering poorly. Which looked something like this.
For a moment I thought, “Did I end up building a 🖨 printer simulator app?”
Overall customer satisfaction will take a hit with such poor loading UX (even if the rest of the app is great). This is especially true for media-heavy apps.
Alright, Let’s see what we can do to fix this.
Load and Fire 🔫
Let the browser download the image and render it.
The perfect moment to render an image is after downloading completely. Till then we just show a loader/placeholder and hide the image.
We can achieve this by using React’s onLoad event on the image tag. You can read more about React.js events here.
<img onLoad={'callbackAfterImageIsDownloaded'} />
Code it
We will create a functional component and use hooks to maintain a couple of states. If you are new to React Hooks, You can learn more here.
// RenderSmoothImage.jsx
function RenderSmoothImage({src, alt}) {
const [imageLoaded, setImageLoaded]=React.useState(false);
return (
<div className="smooth-image-wrapper">
<img
src={src}
alt={alt}
className={`smooth-image image-${
imageLoaded ? 'visible' : 'hidden'
}`}
onLoad={()=> setImageLoaded(true)}}
/>
{!imageLoaded && (
<div className="smooth-preloader">
<span className="loader" />
</div>
)}
</div>
)
}
/** styles.css */
.smooth-image {
transition: opacity 1s;
}
.image-visible {opacity: 1}
.image-hidden {opacity: 0}
Here, we maintain a state imageLoaded
defaults to false
. Which will then be set to true
, once the image is downloaded. We use the onLoad
event to trigger this.
Then we use imageLoaded
state to conditionally add classes to the img
tag, image-visible
vs image-hidden
. We can add transitions/animations to make it smoother. Please refer to the linked Gist at the top for complete styles.
That’s it! No more printer simulators on the page.
What if Image Download Fails / Invalid Src?
By using the alt
attribute we can show alternate text for the image. However, the default icon and styling isn’t too great. To fix this we can display custom alt
text.
// RenderSmoothImage.jsx
function RenderSmoothImage({src, alt}) {
.....
const [isValidSrc, setIsValidSrc] = React.useState(!!src);
return (
<div className="smooth-image-wrapper">
{isValidSrc ? (
<img
....
onError={() => setIsValidSrc(false)}
/>
) : (
<div className="smooth-no-image">{alt}</div>
)}
{isValidSrc && !imageLoaded && (
<div className="smooth-preloader">
<span className="loader" />
</div>
)}
</div>
)
}
/** styles.css */
......
.smooth-no-image {
background-image: linear-gradient(90deg,#ccc,#999,#ccc);
color: #fff;
}
There you go,
You can style the Alternative text any way you want.
I made things easy for you and published a light-weight npm package render-smooth-image-react.
Thank you for reading this post, This is Sai Krishna Prasad, a self-taught and passionate web developer. Signing off Bubye….. until next time.
Top comments (13)
Tomasz Sterna
Interesting points to think about. Thanks!
Loading time can be reduced by caching/preloading the image - I will do another post on how to do this (Thanks for the idea).
When I started with this component my main focus was to keep it simple and beginner friendly.
So, I didn't pay much attention on "preview". With progressive encoding/loading UX would be lot better, best example here would be Medium.
I will add in later versions of the component.
Yes, this is one downside to having placeholder. But, without placeholder or progressive encoding, its a bad UX unless the network is fast enough to load images quickly.
Thanks!
Great post. Will definitely use in one of my projects.
I am glad, it's helpful. Thank you.
Interesting stuff. Great thinking.
Thank you.
So cool.
Thank you.
great stuff
Thank you.
This awesome, thank you
Thank you.
That's such a great idea. Also using progressive images would be an elegant solution.
Yes, Thank you!
Some comments have been hidden by the post's author - find out more