Next/Image placeholder skeleton background #35675
Replies: 4 comments 3 replies
-
Hello! You could leverage the image events such as onload. For exemple I'm doing something like: const [isLoaded, setIsLoaded] = useState(false)
{!isLoaded && <LoadingState />}
<NextImage
onLoad={() => setIsLoaded(true)}
{...props}
/> |
Beta Was this translation helpful? Give feedback.
-
Create an abstraction: export const Image = ({ css, ...props }: { css?: any } & Omit<ImageProps, 'onLoadingComplete'>) => {
const [isLoaded, setIsLoaded] = useState(false);
const [isSkeleton, setIsSkeleton] = useState(skeleton);
return (
<div
style={{
position: 'relative',
inlineSize: '100%',
overflow: 'hidden',
'@keyframes shimmer': {
from: {
transform: 'translateX(-100%)',
},
to: {
transform: 'translateX(100%)',
},
},
'&.skeleton': {
background: 'var(--gray-4)',
'&::before': {
content: '',
position: 'absolute',
inset: 0,
backgroundImage: `linear-gradient(
90deg,
rgba(255, 255, 255, 0) 0,
rgba(255, 255, 255, 0.2) 20%,
rgba(255, 255, 255, 0.5) 60%,
rgba(255, 255, 255, 0)
)`,
animation: 'shimmer 2s infinite',
},
},
}}
className={clsx({ skeleton: isSkeleton })}
>
<div
style={{
'&.fade': {
transition: 'opacity 200ms ease',
opacity: 0,
'&[data-loaded="true"]': {
opacity: 1,
},
},
...css,
}}
className={clsx({ fade: transition })}
data-loaded={isLoaded}
/* remove skeleton after transition ends */
onTransitionEnd={event => event.propertyName === 'opacity' && setIsSkeleton(false)}
>
<NextImage
quality={90}
layout="intrinsic"
{...props}
onLoadingComplete={() => setIsLoaded(true)}
/>
</div>
</div>
);
}; |
Beta Was this translation helpful? Give feedback.
-
If your loaded state relies only on CSS matching you can omit use of Example with use of Tailwind: <Image
// other props
data-loaded='false'
onLoad={event => {
event.currentTarget.setAttribute('data-loaded', 'true')
}}
className='data-[loaded=false]:animate-pulse data-[loaded=false]:bg-gray-100/10'
/> |
Beta Was this translation helpful? Give feedback.
-
The problem with anything that uses |
Beta Was this translation helpful? Give feedback.
-
Describe the feature you'd like to request
When loading an image element, I'd like to avoid having to make a url request and the image processing to blur the image and instead use a CSS background on the image. Libraries such as react-loading-skeleton allow you to quickly replace the component with an image, but that complicates your application code with the usage. It would be nice to have an out-of-the-box solution that you can specify the CSS properties for the non-loaded state and then have them overridden on the loaded state.
Describe the solution you'd like
Describe alternatives you've considered
Wrapping the image element in another custom hook that applies this logic but makes it harder to update in the future when new features of the image element come out.
Beta Was this translation helpful? Give feedback.
All reactions