Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/rpearce/react-medium-image-zoom
π π The original medium.com-inspired image zooming library for React (since 2016)
https://github.com/rpearce/react-medium-image-zoom
hacktoberfest image-zoom medium props react react-images reactjs typescript zoom zoom-images zoomable
Last synced: about 23 hours ago
JSON representation
π π The original medium.com-inspired image zooming library for React (since 2016)
- Host: GitHub
- URL: https://github.com/rpearce/react-medium-image-zoom
- Owner: rpearce
- License: bsd-3-clause
- Created: 2016-07-13T18:15:49.000Z (over 8 years ago)
- Default Branch: main
- Last Pushed: 2025-01-17T02:57:11.000Z (5 days ago)
- Last Synced: 2025-01-20T10:45:14.857Z (1 day ago)
- Topics: hacktoberfest, image-zoom, medium, props, react, react-images, reactjs, typescript, zoom, zoom-images, zoomable
- Language: TypeScript
- Homepage: https://rpearce.github.io/react-medium-image-zoom/
- Size: 94.1 MB
- Stars: 1,933
- Watchers: 11
- Forks: 104
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
Awesome Lists containing this project
README
# react-medium-image-zoom
[![npm version](https://img.shields.io/npm/v/react-medium-image-zoom.svg)](https://www.npmjs.com/package/react-medium-image-zoom) [![react-medium-image-zoom bundlejs badge](https://deno.bundlejs.com/?q=react-medium-image-zoom&badge=&config={%22esbuild%22:{%22external%22:[%22react%22,%22react-dom%22]}})](https://bundlejs.com/?q=react-medium-image-zoom) [![npm downloads](https://img.shields.io/npm/dm/react-medium-image-zoom.svg)](https://www.npmjs.com/package/react-medium-image-zoom) [![All Contributors](https://img.shields.io/badge/all_contributors-88-orange.svg)](#contributors-)
The original [medium.com-inspired image zooming](https://medium.design/image-zoom-on-medium-24d146fc0c20)
library for [React](https://reactjs.org).[View the storybook examples](https://rpearce.github.io/react-medium-image-zoom/)
to see various usages.Features:
* ``, including all [`object-fit`](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit)
values, any [`object-position`](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position),
and [`loading="lazy"`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-loading)
* `` and `` with any [`background-image`](https://developer.mozilla.org/en-US/docs/Web/CSS/background-image),
[`background-size`](https://developer.mozilla.org/en-US/docs/Web/CSS/background-size),
and [`background-position`](https://developer.mozilla.org/en-US/docs/Web/CSS/background-position)
* `` with `` and ``
* `` with ``
* ``
* [Custom zoom modal content](#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](https://www.gatsbyjs.com) and [gatsby-plugin-image](https://www.gatsbyjs.com/plugins/gatsby-plugin-image/)
* [Next.js](https://nextjs.org/docs/api-reference/next/image)
* Zero `dependencies`Requirements to know about:
* `` element ([caniuse dialog](https://caniuse.com/dialog))
* `ResizeObserver` ([caniuse ResizeObserver](https://caniuse.com/mdn-api_resizeobserver))
* Package build target is `ES2021`. If you need to support older environments,
run this package through your build system.## Media
* [2024-08-2024 β _React Round Up_ β "Building a Seamless Image Zoom Feature"](https://topenddevs.com/podcasts/react-round-up/episodes/building-a-seamless-image-zoom-feature-rru-265)
## Quickstart
```bash
npm install --save react-medium-image-zoom
``````javascript
import React from 'react'
import Zoom from 'react-medium-image-zoom'
import 'react-medium-image-zoom/dist/styles.css'export const MyImg = () => (
)
```## API
You can pass these options to either the `Uncontrolled` (default) or
`Controlled` components.```typescript
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 .
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 aor , for example.
// Default: 'div'
wrapElement?: 'div' | 'span'// Provide your own custom modal content component.
ZoomContent?: (props: {
img: ReactElement | null;
buttonUnzoom: ReactElement;
onUnzoom: () => void;
}) => ReactElement;// Higher quality image attributes to use on zoom.
zoomImg?: ImgHTMLAttributes// 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.
```typescript
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.```javascript
import React from 'react'
import Zoom from 'react-medium-image-zoom'
import 'react-medium-image-zoom/dist/styles.css'//
export const MyImg = () => (
)//
export const MyDiv = () => (
)//
export const MyPicture = () => (
)//
export const MyFigure = () => (
Photo by Laura Smetsers
)
```### Controlled component
Import the `Controlled` component and the CSS, wrap your image with the
component, and then dictate the `isZoomed` 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 MyComponent = () => {
const [isZoomed, setIsZoomed] = useState(false)const handleZoomChange = useCallback(shouldZoom => {
setIsZoomed(shouldZoom)
}, [])return (
)
}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](./source/styles.css) 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.](https://rpearce.github.io/react-medium-image-zoom/?path=/story/img--modal-figure-caption)
Below is some example code that demonstrates how to use this feature.
```javascript
export const MyImg = () => (
)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}
{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
Here are the prop changes from `v4` to be aware of:
* `closeText` was renamed to `a11yNameButtonUnzoom`
* `openText` was renamed to `a11yNameButtonZoom`
* `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 `` element now
* `transitionDuration` 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 in `v5.1.0`
* `wrapStyle` was removed
* `zoomZindex` was removed, for we are using the `` element nowAnd you can now provide `zoomImg` props to specify a different image to load when zooming.
## Contributors β¨
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
Robert Pearce
π» π¬ β οΈ π π‘ π¨ π π€ π
Cameron Bothner
π» π π π‘ π€ π β οΈ
Jeremy Bini
π» π
ismay
π π€
Rajit Singh
π
Roberto Saccon
π
wtfdaemon
π
Josh Sloat
π π» π‘ π π€ π π¨ π¬
Aswin
π¬
Alex Shelkovskiy
π
Adrian Bindiu
π
Kendall Buchanan
π
Kaycee
π»
Anuj
π π¬
Ludwig Frank
π π»
LX
π π€
Rosen Tomov
π
Tom Moor
π» π
Johan Preynat
π» π
Rahul Gaba
π» π
Spencer Davis
π» π€ π π¨
dnlnvl
π»
Madi
π€
Ben Hood
π€ π π‘ π
Navilan
π€
13806
π
Akshay Kadam (A2K)
π π€
Jake Stewart
π π€
hhh
π
@davalapar
π
Sun Knudsen
π» π π€ π‘ π¬ π β οΈ π
Douglas Galdino
π» π π π€ π‘ π β οΈ
Mohammed Faragallah
π π€ π‘
Youngrok Kim
π» π
Nandhagopal Ezhilmaran
π
Mattia Astorino
π
Dan Wood
π
Zachery C Gentry
π
xmflsct
π
Will.iam
π» β οΈ
Gourav Goyal
π
Joshua Chen
π π»
David Edler
π π»
rikusen0335
π€
Surjith S M
π€
developergunny
π
Khan Mohsin
π¬
Robin Goudeketting
π
Botros Toro
π€
Christian Guevara
π¬
Johan Book
π
Paolo Di Bello
π€
Tommaso De Rossi
π π
Lezan
π π€
Ibrahim H. Sluma
π
Ben Gotow
π
Rubon72
π
wanderingme
π
Thomas Strobl
π π€ π‘ π¬ π
Songkeys
π π€ π‘ π¬ π
AntoineS92
π
Sindre Aubert
π
mx
π
Sander Heling
π
Yida Zhang
π π»
Nir
π
hhatakeyama
π
Paco
π π€
LichLord91
π
just-small-potato
π€
walmsles
π
tenshin
π¬
Steven Tey
π
Sergey
π π» π
Diego Azevedo
π
Faizan Ahmad
π
Kunal L.
π
Kevin Wang
π€
u3u
π€ π
Hong
π»
Wojciech Rok
π» π€
Matija
π
Jiayi Hu
π
Zeit der Forschung
π
Andrei Barabas
π π€
NΓ©meth Benedek
π
iMalFect
π
Karl Horky
π π€ π
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!