useImageOnLoad()

A simple React Hook that helps you improve UX while images are loading. Rather than having an image that "unfolds" from top to bottom, we load a smaller version first which will be blurred and which will be replaced by the normal size image once loaded.

You can see an implementation of this hook on this site: React Gallery. Don't hesitate to take the logic and write your own CSS instead.

The Hook

1import { CSSProperties, useState } from 'react'
2
3interface ImageStyle {
4 thumbnail: CSSProperties
5 fullSize: CSSProperties
6}
7
8interface ImageOnLoadType {
9 handleImageOnLoad: () => void
10 css: ImageStyle
11}
12
13function useImageOnLoad(): ImageOnLoadType {
14 const [isLoaded, setIsLoaded] = useState<boolean>(false)
15
16 // Triggered when full image will be loaded.
17 const handleImageOnLoad = () => {
18 setIsLoaded(true)
19 }
20
21 const css: ImageStyle = {
22 // Thumbnail style.
23 thumbnail: {
24 visibility: isLoaded ? 'hidden' : 'visible',
25 filter: 'blur(8px)',
26 transition: 'visibility 0ms ease-out 500ms',
27 },
28 // Full image style.
29 fullSize: {
30 opacity: isLoaded ? 1 : 0,
31 transition: 'opacity 500ms ease-in 0ms',
32 },
33 }
34
35 return { handleImageOnLoad, css }
36}
37
38export default useImageOnLoad

Usage

1import React, { CSSProperties } from 'react'
2
3import { useImageOnLoad } from 'usehooks-ts'
4
5export default function Component() {
6 const { handleImageOnLoad, css } = useImageOnLoad()
7
8 const style: { [key: string]: CSSProperties } = {
9 wrap: {
10 position: 'relative',
11 width: 400,
12 height: 400,
13 margin: 'auto',
14 },
15 image: {
16 position: 'absolute',
17 top: 0,
18 left: 0,
19 width: `100%`,
20 height: `100%`,
21 },
22 }
23
24 return (
25 <div style={style.wrap}>
26 {/* Small image load fast */}
27 <img
28 style={{ ...style.image, ...css.thumbnail }}
29 src="https://via.placeholder.com/150"
30 alt="thumbnail"
31 />
32 {/* Full size image */}
33 <img
34 onLoad={handleImageOnLoad}
35 style={{ ...style.image, ...css.fullSize }}
36 src="https://via.placeholder.com/600"
37 alt="fullImage"
38 />
39 </div>
40 )
41}

Edit on CodeSandbox

See a way to make this page better?
Edit there »