Accessible medium.com-style image zoom for React
npm install react-medium-image-zoom   
The original medium.com-inspired image zooming
library for React.
View the storybook examples
to see various usages.
Features:
* Requirements to know about: * * 2024-08-2024 β _React Round Up_ β "Building a Seamless Image Zoom Feature" `` ` export const MyImg = () => ( You can pass these options to either the Uncontrolled ` // Accessible label text for when you want to zoom. // Allow swipe gesture to unzoom. // Your image (required). // Custom CSS className to add to the zoomed // Provide your own unzoom button icon. // Provide your own zoom button icon. // Disables the zoom/unzoom behavior. // First argument: boolean value of a new zoomed state (Uncontrolled // Swipe gesture threshold after which to unzoom. // Specify what type of element should be used for or // Provide your own custom modal content component. // Higher quality image attributes to use on zoom. // Offset in pixels the zoomed image should You can pass these options to only the Controlled ` // Tell the component whether or not it should be zoomed Import the component and the CSS, wrap your image with the component, and the ` // // // // Import the Controlled ` const MyComponent = () => { const handleZoomChange = useCallback(shouldZoom => { return ( export default MyComponent The onZoomChange You can import the default styles from react-medium-image-zoom/dist/styles.css An example of customizing the transition duration, timing function, overlay If you want to customize the zoomed modal experience with a caption, form, or View the live example of custom zoom modal content. Below is some example code that demonstrates how to use this feature. ` const CustomZoomContent = ({ /* Current state of the zoom modal: UNLOADED, LOADING, LOADED, UNLOADING / /* Your image, prepped for zooming / /* A state to check if the zoom img is loaded (useful for loading state) / /** useLayoutEffect(() => { const classCaption = isLoaded return <> Here are the prop changes from v4 * closeText And you can now provide zoomImg` props to specify a different image to load when zooming. Thanks goes to these wonderful people (emoji key): This project follows the all-contributors specification. Contributions of any kind welcome!, including all object-fit
values, any object-position,
and loading="lazy"
* and with any background-image,
background-size,
and background-position
* with and
* with
*
* Custom zoom modal content (π)
* Accessibility:
* JAWS in Chrome, Edge, and Firefox (Windows)
* NVDA in Chrome, Edge, and Firefox (Windows)
* VoiceOver in Safari (macOS, iOS)
* TalkBack in Chrome (Android)
* Supports popular tools:
* Gatsby and gatsby-plugin-image
* Next.js
* Zero dependencies element (caniuse dialog)
* ResizeObserver (caniuse ResizeObserver)
* Package build target is ES2021. If you need to support older environments,
run this package through your build system.Media and Tutorials
* Build a React.js Image Zoom Feature with react-medium-image-zoom Library and State ManagementQuickstart
bash`
npm install --save react-medium-image-zoomjavascript
import React from 'react'
import Zoom from 'react-medium-image-zoom'
import 'react-medium-image-zoom/dist/styles.css'
alt="That Wanaka Tree, New Zealand by Laura Smetsers"
src="/path/to/thatwanakatree.jpg"
width="500"
/>
)
`API
(default) orControlled components.typescript
export interface UncontrolledProps {
// Accessible label text for when you want to unzoom.
// Default: 'Minimize image'
a11yNameButtonUnzoom?: string
// Default: 'Expand image'
a11yNameButtonZoom?: string
// Default: true
canSwipeToUnzoom?: boolean
children: ReactNode
// Default: ICompress
IconUnzoom?: ElementType
// Default: IEnlarge
IconZoom?: ElementType
// Default: false
isDisabled?: boolean
// component) or a suggested new state (Controlled component).
// Second argument: object containing the event that triggered the change.
// Default: undefined
onZoomChange?: (
value: boolean,
data: { event: React.SyntheticEvent | Event }
) => void
// Default: 10
swipeToUnzoomThreshold?: number
// internal component usage. This is useful if the
// image is inside a
ZoomContent?: (props: {
img: ReactElement | null;
buttonUnzoom: ReactElement
onUnzoom: () => void;
}) => ReactElement;
zoomImg?: ImgHTMLAttributes
// be from the window's boundaries.
// Default: 0
zoomMargin?: number
}
` component.typescript
export interface ControlledProps {
// ...same as UncontrolledProps
// Default: false
isZoomed: boolean
}
`Basic Usage
$3
component will handle it's own state.javascript
import React from 'react'
import Zoom from 'react-medium-image-zoom'
import 'react-medium-image-zoom/dist/styles.css'
export const MyImg = () => (
alt="That Wanaka Tree, New Zealand by Laura Smetsers"
src="/path/to/thatwanakatree.jpg"
width="500"
/>
)
export const MyDiv = () => (
aria-label="That Wanaka Tree, New Zealand by Laura Smetsers"
role="img"
style={{
backgroundColor: '#fff',
backgroundImage: url("/path/to/thatwanakatree.jpg"),
backgroundPosition: '50%',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover',
height: '0',
paddingBottom: '56%',
width: '100%',
}}
/>
)
export const MyPicture = () => (
alt="A beautiful, serene setting in nature"
src="/path/to/thatwanakatree.jpg"
width="500"
/>
)
export const MyFigure = () => (
alt="That Wanaka Tree, New Zealand by Laura Smetsers"
src="/path/to/thatwanakatree.jpg"
width="500"
/>
)
`$3
component and the CSS, wrap your image with theisZoomed
component, and then dictate the state to the component.javascript
import React, { useCallback, useState } from 'react'
import { Controlled as ControlledZoom } from 'react-medium-image-zoom'
import 'react-medium-image-zoom/dist/styles.css'
const [isZoomed, setIsZoomed] = useState(false)
setIsZoomed(shouldZoom)
}, [])
alt="That wanaka tree, alone in the water near mountains"
src="/path/to/thatwanakatree.jpg"
width="500"
/>
)
}
` prop accepts a callback that will receive true or false
based on events that occur (like click or scroll events) to assist you in
determining when to zoom and unzoom the component.Styles
rem
and override the values from your code, or you can copy the styles.css
file and alter it to your liking. The latter is the best
option, given s should be used instead of px to account for different
default browser font sizes, and it's hard for a library to guess at what these
values should be.
background color, and unzoom button styles with :focus-visible can be found in
this story: https://rpearce.github.io/react-medium-image-zoom/?path=/story/img--custom-modal-styles$3
other set of components, you can do so by providing a custom component to the
ZoomContent prop.javascript
export const MyImg = () => (
alt="That Wanaka Tree, New Zealand by Laura Smetsers"
src="/path/to/thatwanakatree.jpg"
width="500"
/>
)
/* Default unzoom button /
buttonUnzoom,
modalState,
img,
// isZoomImgLoaded,
* A callback to manually unzoom the image and close the modal if you want to
* use your own buttons or listeners in your custom experience.
*/
//onUnzoom,
}) => {
const [isLoaded, setIsLoaded] = useState(false)
if (modalState === 'LOADED') {
setIsLoaded(true)
} else if (modalState === 'UNLOADING') {
setIsLoaded(false)
}
}, [modalState])
? 'zoom-caption zoom-caption--loaded'
: 'zoom-caption'
{buttonUnzoom}
{img}
That Wanaka Tree, also known as the Wanaka Willow, is a willow tree
located at the southern end of Lake WΔnaka in the Otago region of New
Zealand.
Wikipedia,
That Wanaka Tree
>
}
`Migrating From v4 to v5
to be aware of: was renamed to a11yNameButtonUnzoomopenText
* was renamed to a11yNameButtonZoomoverlayBgColorStart
* was removed and is now controlled via the CSS selector [data-rmiz-modal-overlay="hidden"]overlayBgColorEnd
* was removed and is now controlled via the CSS selector [data-rmiz-modal-overlay="visible"]portalEl
* was removed, for we are using the Contributors β¨