Skip to content

Commit

Permalink
Prevent layout shift when zooming
Browse files Browse the repository at this point in the history
  • Loading branch information
SamyPesse committed Mar 25, 2024
1 parent d6ebb86 commit 2890759
Showing 1 changed file with 29 additions and 7 deletions.
36 changes: 29 additions & 7 deletions src/components/utils/ZoomImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export function ZoomImage(
const [zoomable, setZoomable] = React.useState(false);
const [active, setActive] = React.useState(false);
const [opened, setOpened] = React.useState(false);
const [placeholderRect, setPlaceholderRect] = React.useState<DOMRect | null>(null);

// Only allow zooming when image will not actually be larger and on mobile
React.useEffect(() => {
Expand All @@ -36,10 +37,17 @@ export function ZoomImage(

const mediaQueryList = window.matchMedia('(min-width: 768px)');
const resizeObserver =
width && typeof ResizeObserver !== 'undefined'
typeof ResizeObserver !== 'undefined'
? new ResizeObserver((entries) => {
viewWidth = entries[0]?.contentRect.width;
onChange();
const imgEntry = entries[0];

// Since the image is removed from the DOM when the modal is opened,
// We only care when the size is defined.
if (imgEntry && imgEntry.contentRect.width !== 0) {
viewWidth = entries[0]?.contentRect.width;
setPlaceholderRect(entries[0].contentRect);
onChange();
}
})
: null;

Expand Down Expand Up @@ -104,11 +112,25 @@ export function ZoomImage(
return (
<>
{opened ? (
ReactDOM.createPortal(
<ZoomImageModal src={src} alt={alt ?? ''} onClose={onClose} />,
document.body,
)
<>
{placeholderRect ? (
// Placeholder to keep the layout stable when the image is removed from the DOM
<span
style={{
display: 'block',
width: placeholderRect.width,
height: placeholderRect.height,
}}
/>
) : null}

{ReactDOM.createPortal(
<ZoomImageModal src={src} alt={alt ?? ''} onClose={onClose} />,
document.body,
)}
</>
) : (
// When zooming, remove the image from the DOM to let the browser animates it with View Transition.
<img
ref={imgRef}
{...props}
Expand Down

0 comments on commit 2890759

Please sign in to comment.