medium-zoom
Medium zoom on your images in vanilla JavaScript π πΌ
Table of contents
Features
- π± Responsive β scale on mobile and desktop
- π Performant and lightweight β should be able to reach 60 fps
- β‘οΈ High definition support β load the HD version of your image on zoom
- π Image selection β apply the zoom to a selection of images
- π± Mouse, keyboard and gesture friendly β click anywhere, press a key or scroll away to dismiss the zoom
- π Event handling β trigger events when the zoom enters a new state
- π§ Customization β set your own margin, background and scroll offset
- π Custom templates β extend the default look to match your UI
- π Link support β open the link of the image in a new tab when a meta key is held (β or Ctrl)
- πΌ Image opener β when no link, open the image source in a new tab when a meta key is held (β or Ctrl)
Installation
This module is available on the npm registry, with no dependencies.
npm install --save medium-zoom
# or
yarn add medium-zoom
If you want to use the CDN version:
<script src="https://unpkg.com/medium-zoom@0/dist/medium-zoom.min.js"></script>
To use a local version, you can download the minified version of the module.
Usage
1. Import the script
You can skip this step if you use the CDN version.
Import the script:
<script src="node_modules/medium-zoom/dist/medium-zoom.min.js"></script>
Or, using imports:
import mediumZoom from 'medium-zoom'
That's it! You don't need to import any CSS styles.
2. Use the library
mediumZoom(<selector>, <options>)
By default, the zoom is applied to all scaled images (with HTML or CSS properties). You can specify the zoomable images with a CSS selector and add options.
Additionally, you can pass an HTML Element, a NodeList, an HTMLCollection or an array of images to the plugin.
// CSS selector
mediumZoom('#cover')
// HTML Element
mediumZoom(document.getElementById('cover'))
// NodeList
mediumZoom(document.querySelectorAll('[data-action="zoom"]'))
// HTMLCollection
mediumZoom(document.images)
// Array
const imagesToZoom = [
document.querySelector('#cover'),
...document.querySelectorAll('[data-action="zoom"]')
]
mediumZoom(imagesToZoom)
API
Options
Options can be passed via a JavaScript object through the mediumZoom
call.
Property | Type | Default | Description |
---|---|---|---|
margin |
number |
0 |
The space outside the zoomed image |
background |
string |
"#fff" |
The color of the overlay |
scrollOffset |
number |
48 |
The number of pixels to scroll to dismiss the zoom |
metaClick |
boolean |
true |
Enables the action on meta click (opens the link / image source) |
container |
string |Element |object |
The element to render the zoom in or a viewport object. Read more β | |
template |
string |Element |
The template element to show on zoom. Read more β |
mediumZoom('[data-action="zoom"]', {
margin: 24,
background: '#000',
scrollOffset: 0,
metaClick: false,
container: '#zoom-container',
template: '#zoom-template'
})
container
Using a custom The zoom is by default rendered in the window viewport. You can also render your image in any element of the DOM, or any custom coordinates with the container
option.
Rendering in a DOM Element
<article>
<p>My article...</p>
<img src="image.jpg" alt="My image">
<div id="zoom-container"></div>
</article>
<script>
mediumZoom('img', {
container: '#zoom-container' // or document.querySelector('#zoom-container')
})
</script>
Rendering with coordinates
If you don't already have an element in your DOM to specify the position of the zoom, you can pass an object with the following number
properties:
mediumZoom('img', {
container: {
width: 720,
height: 480,
top: 64,
bottom: 64,
right: 0,
left: 0
}
})
These properties behave very much like Element.getBoundingClientRect()
. They will get merged with the default ones so you don't need to specify all of them.
The default width
and height
are window.innerWidth
and window.innerHeight
. Others are set to 0
.
template
Using a custom You might want to render the zoom in your own template. You could reproduce zooms as seen on Facebook or Dropbox Paper. This is possible with the template
option.
- Create a
template
element matching thetemplate
option value - If you'd like your image to appear at a specific position in your template, specify the
container
option and add it in your template (#zoom-container
here)
<template id="zoom-template">
<div>
<header>My image zoom template</header>
<div id="zoom-container"></div>
<aside>Comment on my image</aside>
</div>
</template>
<script>
mediumZoom('[data-action="zoom"]', {
template: '#zoom-template',
container: '#zoom-container'
})
</script>
Go to the examples/
folder for more details.
Methods
.show()
Triggers the zoom.
const zoom = mediumZoom('#my-image')
zoom.show()
Emits an event show
on animation start and shown
when completed.
.hide()
Dismisses the zoom.
const zoom = mediumZoom('#my-image')
zoom.hide()
Emits an event hide
on animation start and hidden
when completed.
.toggle()
Shows the zoom when hidden, hides the zoom when shown.
const zoom = mediumZoom('#my-image')
zoom.toggle()
.update(<options>)
Updates and returns the options.
const zoom = mediumZoom('#my-image')
zoom.update({
background: '#000'
})
.detach()
Releases the images related to the zoom from the plugin.
const zoom = mediumZoom('#my-image')
zoom.detach()
Emits an event detach
.
.addEventListeners(type, listener)
Registers the specified listener on each target of the zoom.
const zoom = mediumZoom('[data-action="zoom"]')
zoom.addEventListeners('hidden', () => {
// do something...
})
Data attributes
data-zoom-target
Specifies the high definition image to show on zoom. This image is loaded when the user clicks on the source image, only once.
<img
src="image-thumb.jpg"
data-zoom-target="image-hd.jpg"
alt="My image"
>
Events
Event | Description |
---|---|
show | Fired immediately when the show instance method is called |
shown | Fired when the zoom has finished being animated |
hide | Fired immediately when the hide instance method is called |
hidden | Fired when the zoom out has finished being animated |
detach | Fired when the detach instance method is called |
const zoom = mediumZoom('#image-tracked')
zoom.addEventListeners('show', event => {
// do something...
})
Examples
Declare zoomable images with data attributes
A common pattern to declare images as zoomable is to use data attributes.
mediumZoom('[data-action="zoom"]')
Attach a zoom dynamically
When using a framework that mounts your component several times, you don't want to apply a zoom multiple times to the same image. You can apply the CSS selector :not(.medium-zoom-image)
to your selection of images. The CSS class .medium-zoom-image
is added to your image the first time medium-zoom
is attached.
mediumZoom('img:not(.medium-zoom-image)')
Attach a zoom to external images
mediumZoom('img[src^="http"]')
Attach a zoom to images from a database
fetch(`https://myapi.com/posts/${postId}`)
.then(response => response.json())
.then(post => {
const imagesToZoom = post.images.map(imgSrc =>
document.querySelector(`img[src=${imgSrc}]`)
)
mediumZoom(imagesToZoom)
})
Attach a zoom using React refs
import React, { Component } from 'react'
import mediumZoom from 'medium-zoom'
class App extends Component {
attachZoom = image => {
mediumZoom(image)
}
render() {
return (
<img src="image.jpg" alt="Image" ref={this.attachZoom} />
)
}
}
Trigger a zoom from another element
You sometimes want to trigger a zoom when the user clicks somewhere else.
const button = document.querySelector('#btn-zoom')
const zoom = mediumZoom('#image')
button.addEventListener('click', () => zoom.show())
Track an event (for analytics)
You can use the show
event to keep track of how many times a user interacts with your image. This can be useful if you want to gather some analytics on user engagement.
let counter = 0
const zoom = mediumZoom('#image-tracked')
zoom.addEventListeners('show', event => {
console.log(`"${event.target.alt}" has been zoomed ${++counter} times`)
})
Detach a zoom after a while
const zoom = mediumZoom('#image-detach')
setTimeout(() => {
zoom.detach()
}, 5000)
Make a zoom clickable only once
const zoomToDetach = mediumZoom('#zoom-detach')
zoomToDetach.addEventListeners('hidden', zoomToDetach.detach)
You can see more examples including vanilla JavaScript, React βοΈ and Vue.
Demo
View demo π, go to the examples folder or read the article.
Browser support
IE | Edge | Chrome | Firefox | Safari |
---|---|---|---|---|
10* | 12* | 36 | 34 | 9 |
* These browsers require a <template>
polyfill when using custom templates.
Dev
- Run
npm install
to install Node dev dependencies - Run
npm run dev
to watch changes and rebuild the library - Open
examples/demo/development/index.html
to check your changes (it includesdist/medium-zoom.min.js
which is watched withnpm run dev
)
More commands
- Lint code:
npm run lint:fix
- Test:
npm test
You can also use Yarn.
Contributing
Need more options? Send a pull request!
License
MIT © François Chalifour