• Stars
    star
    1,779
  • Rank 26,163 (Top 0.6 %)
  • Language
    TypeScript
  • License
    BSD 3-Clause "New...
  • Created over 8 years ago
  • Updated 7 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

๐Ÿ”Ž ๐Ÿž The original medium.com-inspired image zooming library for React (since 2016)

react-medium-image-zoom

npm version bundlephobia size npm downloads All Contributors

The original medium.com-inspired image zooming library for React.

View the storybook examples to see various usages.

Features:

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

  // 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

  // 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 rems 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 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 <dialog> 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 <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):

Robert Pearce
Robert Pearce

๐Ÿ’ป ๐Ÿ’ฌ โš ๏ธ ๐Ÿ› ๐Ÿ’ก ๐ŸŽจ ๐Ÿ‘€ ๐Ÿค” ๐Ÿ“–
Cameron Bothner
Cameron Bothner

๐Ÿ’ป ๐Ÿ“– ๐Ÿ› ๐Ÿ’ก ๐Ÿค” ๐Ÿ‘€ โš ๏ธ
Jeremy Bini
Jeremy Bini

๐Ÿ’ป ๐Ÿ›
ismay
ismay

๐Ÿ› ๐Ÿค”
Rajit Singh
Rajit Singh

๐Ÿ›
Roberto Saccon
Roberto Saccon

๐Ÿ›
wtfdaemon
wtfdaemon

๐Ÿ›
Josh Sloat
Josh Sloat

๐Ÿ› ๐Ÿ’ป ๐Ÿ’ก ๐Ÿ‘€ ๐Ÿค” ๐Ÿ“– ๐ŸŽจ ๐Ÿ’ฌ
Aswin
Aswin

๐Ÿ’ฌ
Alex Shelkovskiy
Alex Shelkovskiy

๐Ÿ›
Adrian Bindiu
Adrian Bindiu

๐Ÿ›
Kendall Buchanan
Kendall Buchanan

๐Ÿ›
Kaycee
Kaycee

๐Ÿ’ป
Anuj
Anuj

๐Ÿ› ๐Ÿ’ฌ
Ludwig Frank
Ludwig Frank

๐Ÿ› ๐Ÿ’ป
LX
LX

๐Ÿ› ๐Ÿค”
Rosen Tomov
Rosen Tomov

๐Ÿ›
Tom Moor
Tom Moor

๐Ÿ’ป ๐Ÿ›
Johan Preynat
Johan Preynat

๐Ÿ’ป ๐Ÿ›
Rahul Gaba
Rahul Gaba

๐Ÿ’ป ๐Ÿ›
Spencer Davis
Spencer Davis

๐Ÿ’ป ๐Ÿค” ๐Ÿ‘€ ๐ŸŽจ
dnlnvl
dnlnvl

๐Ÿ’ป
Madi
Madi

๐Ÿค”
Ben Hood
Ben Hood

๐Ÿค” ๐Ÿ› ๐Ÿ’ก ๐Ÿ‘€
Navilan
Navilan

๐Ÿค”
13806
13806

๐Ÿ›
Akshay Kadam (A2K)
Akshay Kadam (A2K)

๐Ÿ› ๐Ÿค”
Jake Stewart
Jake Stewart

๐Ÿ› ๐Ÿค”
hhh
hhh

๐Ÿ›
@davalapar
@davalapar

๐Ÿ›
Sun Knudsen
Sun Knudsen

๐Ÿ’ป ๐Ÿ› ๐Ÿค” ๐Ÿ’ก ๐Ÿ’ฌ ๐Ÿ‘€ โš ๏ธ ๐Ÿ“–
Douglas Galdino
Douglas Galdino

๐Ÿ’ป ๐Ÿ“– ๐Ÿ› ๐Ÿค” ๐Ÿ’ก ๐Ÿ‘€ โš ๏ธ
Mohammed Faragallah
Mohammed Faragallah

๐Ÿ› ๐Ÿค” ๐Ÿ’ก
Youngrok Kim
Youngrok Kim

๐Ÿ’ป ๐Ÿ›
Nandhagopal Ezhilmaran
Nandhagopal Ezhilmaran

๐Ÿ›
Mattia Astorino
Mattia Astorino

๐Ÿ›
Dan Wood
Dan Wood

๐Ÿ“–
Zachery C Gentry
Zachery C Gentry

๐Ÿ›
xmflsct
xmflsct

๐Ÿ›
Will.iam
Will.iam

๐Ÿ’ป โš ๏ธ
Gourav Goyal
Gourav Goyal

๐Ÿ“–
Joshua Chen
Joshua Chen

๐Ÿ› ๐Ÿ’ป
David Edler
David Edler

๐Ÿ›
rikusen0335
rikusen0335

๐Ÿค”
Surjith S M
Surjith S M

๐Ÿค”
developergunny
developergunny

๐Ÿ›
Khan Mohsin
Khan Mohsin

๐Ÿ’ฌ
Robin Goudeketting
Robin Goudeketting

๐Ÿ›
Botros Toro
Botros Toro

๐Ÿค”
Christian Guevara
Christian Guevara

๐Ÿ’ฌ
Johan Book
Johan Book

๐Ÿ›
Paolo Di Bello
Paolo Di Bello

๐Ÿค”
Tommaso De Rossi
Tommaso De Rossi

๐Ÿ“– ๐Ÿ›
Lezan
Lezan

๐Ÿ› ๐Ÿค”
Ibrahim H. Sluma
Ibrahim H. Sluma

๐Ÿ›
Ben Gotow
Ben Gotow

๐Ÿ›
Rubon72
Rubon72

๐Ÿ›
wanderingme
wanderingme

๐Ÿ›
Thomas Strobl
Thomas Strobl

๐Ÿ› ๐Ÿค” ๐Ÿ’ก ๐Ÿ’ฌ ๐Ÿ‘€
Songkeys
Songkeys

๐Ÿ› ๐Ÿค” ๐Ÿ’ก ๐Ÿ’ฌ ๐Ÿ‘€
AntoineS92
AntoineS92

๐Ÿ›
Sindre Aubert
Sindre Aubert

๐Ÿ›
mx
mx

๐Ÿ›
Sander Heling
Sander Heling

๐Ÿ›
Yida Zhang
Yida Zhang

๐Ÿ› ๐Ÿ’ป
Nir
Nir

๐Ÿ›
hhatakeyama
hhatakeyama

๐Ÿ›
Paco
Paco

๐Ÿ› ๐Ÿค”
LichLord91
LichLord91

๐Ÿ›
just-small-potato
just-small-potato

๐Ÿค”
walmsles
walmsles

๐Ÿ›

This project follows the all-contributors specification. Contributions of any kind welcome!

More Repositories

1

react-expanding-textarea

React textarea component to automatically expand and contract your textareas.
TypeScript
89
star
2

hakyll-nix-template

Hakyll + Nix starter template
Haskell
50
star
3

parse-md

Parse Markdown file's metadata from its content
TypeScript
36
star
4

react-static

(not maintained) React static site generator framework for Node.js
JavaScript
27
star
5

keep_awake

(not maintained) Give your app a good wakeup call with KeepAwake. The sleeper must awaken.
CSS
21
star
6

dotfiles

๐Ÿชด my dotfile garden ๐ŸŒฑ
Shell
14
star
7

nix-rust-template

A reasonable way to start developing a reproducible Rust project
Nix
13
star
8

ramda.guide

Ramda Guide
Rust
11
star
9

bashcards

Practice flashcards in your terminal
Shell
11
star
10

robertwpearce.com

๐Ÿ’พ My personal site; built with hakyll
CSS
8
star
11

slugger

Clean URI slugs for Haskell
Haskell
8
star
12

ts-fns

โš ๏ธ experimentation with typescript and functions
TypeScript
7
star
13

react-form-steps-example

Form steps example with React.js
CSS
7
star
14

timetrack-cli

โณ Use the command line to keep track of your working hours in plain text files; similar to https://github.com/ginatrapani/todo.txt-cli.
Haskell
6
star
15

bertstrap

(old and unused) Library for generic SCSS mixins and colour variables
CSS
6
star
16

riotjs-examples

Demo using RiotJS
JavaScript
5
star
17

hex

๐ŸŽจ Hexadecimal color code & RGBa utility functions
TypeScript
5
star
18

react-with-forwarded-ref

React higher-order component (HOC) for ref forwarding
TypeScript
5
star
19

react-popover-a11y

๐ŸŒˆ Accessible React popover component
JavaScript
4
star
20

example-component-library

๐ŸŒˆ Example repository for a shared React components library
TypeScript
4
star
21

mgmt

โš™๏ธ Use nix to manage your CLI tools, configuration dotfiles, and more
Nix
3
star
22

ature

Temperature conversion CLI tool written in Go
Go
3
star
23

crash-courses

Repo for crash course materials
HTML
3
star
24

frontend-template

Frontend template. Uses Sass, Browserify, CoffeeScript, Mocha + Chai, React + Flux + React Accessibility.
CSS
2
star
25

geocoding-proxy

Google Maps API Geocoding Proxy Server
JavaScript
2
star
26

httpwut

CLI tool to look up HTTP status codes written in Go
Go
2
star
27

dear-dia11y

Confessions of a programmer working on web accessibility
Nix
2
star
28

acts_as_loose_tenant

Multi-multi-tenancy
Ruby
2
star
29

Hairoku

Haiku on Heroku - Hairoku | Built with Ruby, Sinatra, MongoMapper, HAML, jQuery, and Skeleton CSS
JavaScript
2
star
30

BarCampCHS

To be used as a resource for BarCampCHS!
JavaScript
1
star
31

elm-step-form

JavaScript
1
star
32

evsouth

Ruby
1
star
33

converge-reactjs-demo

Demo for Converge talk on ReactJS
CSS
1
star
34

uk-rainfall-data-demo

Ruby
1
star
35

flexible-string-replace

๐Ÿงถ Safely replace any part of a string with anything. Example: useful for replacing substrings with JSX in React. Replaces https://github.com/rpearce/highlightify and descendent of ideas for trying to fix https://github.com/iansinnott/react-string-replace
JavaScript
1
star
36

oh_you_sassy

Damn, you sassy. App made with Padrino, SASS/SCSS, HAML, DataMapper
JavaScript
1
star
37

teaching

CSS
1
star
38

SCGOPrimaryTweets

Mini-service that tracks the tweets of South Carolinians leading up to the SC GOP Primary.
Ruby
1
star
39

haskell-nix-example

Haskell and nix example project
Nix
1
star
40

datapad

Star Wars Character Testing API
Ruby
1
star
41

test-axe

TypeScript
1
star
42

rpearce

1
star
43

talk-ramda-rainfall

TypeScript
1
star
44

javascript101

JavaScript
1
star
45

skeleton-Sass

Sass port of the great Skeleton (www.getskeleton.com)
1
star
46

simple-uniqueid

Generate simple unique ids
JavaScript
1
star
47

highlightify

(unmaintained; use https://github.com/rpearce/flexible-string-replace instead) Highlight portions of text given text, a filter and an optional className.
JavaScript
1
star
48

elm-geocoding-darksky

Code for blog post series on Elm, Geocoding & DarkSky from https://robertwpearce.com
Elm
1
star
49

demo-structure-node-postgres

Demo for node PG structure
JavaScript
1
star
50

writing

All my writing in one place
1
star
51

oh_you_sassy-ConvergeSE

To be used as an aid to my ConvergeSE 2012 workshop on SASS/SCSS and styling frameworks like Twitter Bootstrap, Skeleton, and 960.
JavaScript
1
star
52

CharlestonLiteracy.org

Redesigned site for Charleston Volunteers for Literacy
JavaScript
1
star
53

minitest-given-rails-example

MiniTest and minitest-given Rails example
Ruby
1
star
54

altioralabs.com

Altiora Labs, LLC
CSS
1
star
55

charleston-literacy

Content Management System for Charleston Volunteers for Literacy
Ruby
1
star
56

hakyll-nix-example

Example project for building hakyll projects with nix
Nix
1
star
57

DarkSky-proxy

Node.JS proxy for DarkSky
JavaScript
1
star
58

compare-pizza-deals

Elm
1
star
59

the-blake-house.com

HTML
1
star
60

obviouslee

PHP
1
star
61

immutable-array-insert

Easily insert items in an array without mutating the original array.
JavaScript
1
star
62

emilyandrobert.wedding

Information for the big day!
JavaScript
1
star
63

ikon

JavaScript
1
star
64

task-from-fn

[migrated to https://origamitower.github.io/folktale/en/folktale.data.task.fromnodeback.html] Wrap a JavaScript function that has a callback in a Task (data.task)
JavaScript
1
star
65

react-button-a11y

โŒจ๏ธ โœ… Make non-button elements accessible in React
JavaScript
1
star