react-medium-image-zoom
🔎 🏞 The original medium.com-inspired image zooming library for React (since 2016)
Top Related Projects
Easily add "zoom on hover" functionality to your site's images. Lightweight, no-dependency JavaScript.
🔎🖼 A JavaScript library for zooming images like Medium
Fork of fat/zoom.js with improvements
Quick Overview
React Medium Image Zoom is a lightweight React component that allows for easy implementation of medium.com-style image zooming. It provides a smooth and intuitive way to zoom in on images within a React application, enhancing the user experience for viewing image details.
Pros
- Easy to integrate into existing React projects
- Customizable appearance and behavior
- Supports both controlled and uncontrolled components
- Lightweight with minimal dependencies
Cons
- Limited to React applications only
- May require additional setup for complex image layouts
- Zoom functionality might not be necessary for all types of websites
- Could potentially conflict with other image-related libraries or components
Code Examples
- Basic usage:
import React from 'react'
import Zoom from 'react-medium-image-zoom'
import 'react-medium-image-zoom/dist/styles.css'
function MyComponent() {
return (
<Zoom>
<img
alt="A beautiful landscape"
src="/path/to/image.jpg"
width="500"
/>
</Zoom>
)
}
- Controlled component with custom styles:
import React, { useState } from 'react'
import Zoom from 'react-medium-image-zoom'
import 'react-medium-image-zoom/dist/styles.css'
function ControlledZoom() {
const [isZoomed, setIsZoomed] = useState(false)
return (
<Zoom
isZoomed={isZoomed}
onZoomChange={setIsZoomed}
zoomMargin={40}
overlayBgColorEnd="rgba(0, 0, 0, 0.85)"
>
<img
alt="A controlled zoomable image"
src="/path/to/controlled-image.jpg"
width="300"
/>
</Zoom>
)
}
- Using with next/image in Next.js:
import React from 'react'
import Image from 'next/image'
import Zoom from 'react-medium-image-zoom'
import 'react-medium-image-zoom/dist/styles.css'
function NextJsZoom() {
return (
<Zoom>
<Image
src="/path/to/nextjs-image.jpg"
alt="Next.js compatible zoomable image"
width={500}
height={300}
/>
</Zoom>
)
}
Getting Started
-
Install the package:
npm install react-medium-image-zoom
-
Import the component and styles in your React file:
import Zoom from 'react-medium-image-zoom' import 'react-medium-image-zoom/dist/styles.css'
-
Wrap your image with the Zoom component:
<Zoom> <img src="/path/to/your/image.jpg" alt="Zoomable image" /> </Zoom>
-
Customize the Zoom component props as needed for your specific use case.
Competitor Comparisons
Easily add "zoom on hover" functionality to your site's images. Lightweight, no-dependency JavaScript.
Pros of Drift
- Supports multiple image zoom techniques (lens, window, inner)
- Offers touch device support and mobile-friendly features
- Provides more customization options for zoom behavior
Cons of Drift
- Less focused on React integration compared to React Medium Image Zoom
- May require more setup and configuration for basic use cases
- Documentation is less comprehensive
Code Comparison
React Medium Image Zoom:
import React from 'react'
import Zoom from 'react-medium-image-zoom'
function MyComponent() {
return <Zoom><img src="image.jpg" alt="Zoomable image" /></Zoom>
}
Drift:
import Drift from 'drift-zoom'
new Drift(document.querySelector('img'), {
paneContainer: document.querySelector('p'),
inlinePane: false
})
Summary
Drift offers more versatile zoom options and better touch device support, making it suitable for complex image zoom requirements. However, React Medium Image Zoom provides a more straightforward integration for React projects and may be easier to implement for basic use cases. The choice between the two depends on the specific needs of the project, with Drift being more flexible but potentially requiring more setup, while React Medium Image Zoom offers a simpler React-focused solution.
🔎🖼 A JavaScript library for zooming images like Medium
Pros of medium-zoom
- Framework-agnostic: Can be used with any JavaScript project, not limited to React
- Lighter weight: Smaller bundle size and fewer dependencies
- More customizable: Offers more options for styling and behavior
Cons of medium-zoom
- Less React-specific: Doesn't provide React-specific optimizations or hooks
- Manual integration: Requires more setup in React projects compared to a dedicated React component
- Limited TypeScript support: Less robust type definitions compared to react-medium-image-zoom
Code Comparison
react-medium-image-zoom:
import { Controlled as ControlledZoom } from 'react-medium-image-zoom'
<ControlledZoom isZoomed={isZoomed} onZoomChange={handleZoomChange}>
<img src="image.jpg" alt="Zoomable image" />
</ControlledZoom>
medium-zoom:
import mediumZoom from 'medium-zoom'
mediumZoom(document.querySelector('img'))
Both libraries provide image zooming functionality, but medium-zoom offers a more vanilla JavaScript approach, while react-medium-image-zoom is tailored specifically for React applications. The choice between them depends on the project's requirements, framework, and desired level of customization.
Fork of fat/zoom.js with improvements
Pros of zoom.js
- Lightweight and dependency-free, making it easier to integrate into various projects
- Supports both images and other HTML elements for zooming
- Offers more customization options for zoom behavior and appearance
Cons of zoom.js
- Not specifically designed for React, requiring additional setup for React projects
- Less actively maintained, with fewer recent updates and contributions
- May require more manual configuration for responsive designs
Code Comparison
zoom.js:
zoom.setup();
document.querySelector('img').addEventListener('click', function () {
zoom.to({ element: this });
});
react-medium-image-zoom:
import Zoom from 'react-medium-image-zoom'
<Zoom>
<img src="path/to/image.jpg" alt="Zoomable image" />
</Zoom>
Summary
zoom.js is a versatile, lightweight solution for adding zoom functionality to various elements, offering more customization options. However, it may require more setup for React projects and has less recent maintenance. react-medium-image-zoom is specifically designed for React, providing an easier integration process for React applications but with potentially fewer customization options.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
react-medium-image-zoom
The original medium.com-inspired image zooming library for React.
View the storybook examples to see various usages.
Features:
<img />
, including allobject-fit
values, anyobject-position
, andloading="lazy"
<div>
and<span>
with anybackground-image
,background-size
, andbackground-position
<picture>
with<source />
and<img />
<figure>
with<img />
<svg>
- 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:
- Zero
dependencies
Requirements to know about:
<dialog>
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.
Quickstart
npm install --save react-medium-image-zoom
import React from 'react'
import Zoom from 'react-medium-image-zoom'
import 'react-medium-image-zoom/dist/styles.css'
export const MyImg = () => (
<Zoom>
<img
alt="That Wanaka Tree, New Zealand by Laura Smetsers"
src="/path/to/thatwanakatree.jpg"
width="500"
/>
</Zoom>
)
API
You can pass these options to either the Uncontrolled
(default) or
Controlled
components.
export interface UncontrolledProps {
// Accessible label text for when you want to unzoom.
// Default: 'Minimize image'
a11yNameButtonUnzoom?: string
// Accessible label text for when you want to zoom.
// Default: 'Expand image'
a11yNameButtonZoom?: string
// Allow swipe gesture to unzoom.
// Default: true
canSwipeToUnzoom?: boolean
// Your image (required).
children: ReactNode
// Custom CSS className to add to the zoomed <dialog>.
classDialog?: string
// Provide your own unzoom button icon.
// Default: ICompress
IconUnzoom?: ElementType
// Provide your own zoom button icon.
// Default: IEnlarge
IconZoom?: ElementType
// Swipe gesture threshold after which to unzoom.
// Default: 10
swipeToUnzoomThreshold?: number
// Specify what type of element should be used for
// internal component usage. This is useful if the
// image is inside a <p> or <button>, for example.
// Default: 'div'
wrapElement?: 'div' | 'span'
// Provide your own custom modal content component.
ZoomContent?: (props: {
img: ReactElement | null;
buttonUnzoom: ReactElement<HTMLButtonElement>;
onUnzoom: () => void;
}) => ReactElement;
// Higher quality image attributes to use on zoom.
zoomImg?: ImgHTMLAttributes<HTMLImageElement>
// Offset in pixels the zoomed image should
// be from the window's boundaries.
// Default: 0
zoomMargin?: number
}
You can pass these options to only the Controlled
component.
export interface ControlledProps {
// ...same as UncontrolledProps
// Tell the component whether or not it should be zoomed
// Default: false
isZoomed: boolean
// Listen for hints from the component about when you
// should zoom (`true` value) or unzoom (`false` value)
onZoomChange?: (value: boolean) => void
}
Basic Usage
Uncontrolled component (default)
Import the component and the CSS, wrap your image with the component, and the component will handle it's own state.
import React from 'react'
import Zoom from 'react-medium-image-zoom'
import 'react-medium-image-zoom/dist/styles.css'
// <img />
export const MyImg = () => (
<Zoom>
<img
alt="That Wanaka Tree, New Zealand by Laura Smetsers"
src="/path/to/thatwanakatree.jpg"
width="500"
/>
</Zoom>
)
// <div>
export const MyDiv = () => (
<Zoom>
<div
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%',
}}
/>
</Zoom>
)
// <picture>
export const MyPicture = () => (
<Zoom>
<picture>
<source media="(max-width: 800px)" srcSet="/path/to/teAraiPoint.jpg" />
<img
alt="A beautiful, serene setting in nature"
src="/path/to/thatwanakatree.jpg"
width="500"
/>
</picture>
</Zoom>
)
// <figure>
export const MyFigure = () => (
<figure>
<Zoom>
<img
alt="That Wanaka Tree, New Zealand by Laura Smetsers"
src="/path/to/thatwanakatree.jpg"
width="500"
/>
</Zoom>
<figcaption>Photo by Laura Smetsers</figcaption>
</figure>
)
Controlled component
Import the Controlled
component and the CSS, wrap your image with the
component, and then dictate the isZoomed
state to the component.
import React, { useCallback, useState } from 'react'
import { Controlled as ControlledZoom } from 'react-medium-image-zoom'
import 'react-medium-image-zoom/dist/styles.css'
const MyComponent = () => {
const [isZoomed, setIsZoomed] = useState(false)
const handleZoomChange = useCallback(shouldZoom => {
setIsZoomed(shouldZoom)
}, [])
return (
<ControlledZoom isZoomed={isZoomed} onZoomChange={handleZoomChange}>
<img
alt="That wanaka tree, alone in the water near mountains"
src="/path/to/thatwanakatree.jpg"
width="500"
/>
</ControlledZoom>
)
)
export default MyComponent
The onZoomChange
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
You can import the default styles from react-medium-image-zoom/dist/styles.css
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 rem
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.
An example of customizing the transition duration, timing function, overlay
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
Custom zoom modal content
If you want to customize the zoomed modal experience with a caption, form, or
other set of components, you can do so by providing a custom component to the
ZoomContent
prop.
View the live example of custom zoom modal content.
Below is some example code that demonstrates how to use this feature.
export const MyImg = () => (
<Zoom ZoomContent={CustomZoomContent}>
<img
alt="That Wanaka Tree, New Zealand by Laura Smetsers"
src="/path/to/thatwanakatree.jpg"
width="500"
/>
</Zoom>
)
const CustomZoomContent = ({
buttonUnzoom, // default unzoom button
modalState, // current state of the zoom modal: UNLOADED, LOADING, LOADED, UNLOADING
img, // your image, prepped for zooming
//onUnzoom, // unused here, but 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
}) => {
const [isLoaded, setIsLoaded] = useState(false)
useLayoutEffect(() => {
if (modalState === 'LOADED') {
setIsLoaded(true)
} else if (modalState === 'UNLOADING') {
setIsLoaded(false)
}
}, [modalState])
const classCaption = isLoaded
? 'zoom-caption zoom-caption--loaded'
: 'zoom-caption'
return <>
{buttonUnzoom}
<figure>
{img}
<figcaption className={classCaption}>
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.
<cite className="zoom-caption-cite">
Wikipedia, <a className="zoom-caption-link" href="https://en.wikipedia.org/wiki/That_Wanaka_Tree">
That Wanaka Tree
</a>
</cite>
</figcaption>
</figure>
</>
}
Migrating From v4 to v5
Here are the prop changes from v4
to be aware of:
closeText
was renamed toa11yNameButtonUnzoom
openText
was renamed toa11yNameButtonZoom
overlayBgColorStart
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<dialog>
element nowtransitionDuration
was removed and is now controlled via the CSS selectors[data-rmiz-modal-overlay]
and[data-rmiz-modal-img]
wrapElement
was removed then added back inv5.1.0
wrapStyle
was removedzoomZindex
was removed, for we are using the<dialog>
element now
And you can now provide zoomImg
props to specify a different image to load when zooming.
Contributors â¨
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!
Top Related Projects
Easily add "zoom on hover" functionality to your site's images. Lightweight, no-dependency JavaScript.
🔎🖼 A JavaScript library for zooming images like Medium
Fork of fat/zoom.js with improvements
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot