{"id":11294,"library":"medium-zoom","title":"Medium Zoom","description":"Medium Zoom is a lightweight, responsive JavaScript library designed to replicate the elegant image zooming experience found on the Medium platform. Currently stable at version 1.1.0, the package sees active development with regular patch releases addressing bugs and minor enhancements, building upon its significant 1.0.0 refactor. Key differentiators include its high performance (aiming for 60fps), support for high-definition image loading on zoom, extensive customization options for margin, background, and scroll offset, and a pluggable architecture allowing for custom features and templates. It is framework-agnostic, working seamlessly across React, Vue, Angular, Svelte, and Solid, and offers comprehensive event handling for various zoom states. The library focuses on providing a smooth, intuitive user experience that is friendly to mouse, keyboard, and touch gestures.","status":"active","version":"1.1.0","language":"javascript","source_language":"en","source_url":"https://github.com/francoischalifour/medium-zoom","tags":["javascript","medium","image","zoom","picture","lightbox","click","scroll","pure","typescript"],"install":[{"cmd":"npm install medium-zoom","lang":"bash","label":"npm"},{"cmd":"yarn add medium-zoom","lang":"bash","label":"yarn"},{"cmd":"pnpm add medium-zoom","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"The library primarily uses a default export for the main function. While CommonJS `require` might work in some transpiled environments, native ESM import is preferred. Since v1.0.0, the package is built with modern JS targets in mind.","wrong":"const mediumZoom = require('medium-zoom');","symbol":"mediumZoom","correct":"import mediumZoom from 'medium-zoom';"},{"note":"These types are useful for explicit type declarations when working with the zoom instance or its configuration options in TypeScript.","symbol":"Zoom / Options (TypeScript Types)","correct":"import type { Zoom, Options } from 'medium-zoom';"},{"note":"The core CSS is not automatically bundled with the JavaScript and must be imported separately to ensure the zoom animation and overlay are styled correctly. For v1.1.0+, a `medium-zoom.pure.css` bundle is also available, separating JS and CSS further.","wrong":"import 'medium-zoom/medium-zoom.css';","symbol":"CSS Styles","correct":"import 'medium-zoom/dist/medium-zoom.css';"}],"quickstart":{"code":"import mediumZoom from 'medium-zoom';\nimport 'medium-zoom/dist/medium-zoom.css';\n\ndocument.addEventListener('DOMContentLoaded', () => {\n  // Initialize mediumZoom on all images with the class 'zoomable-image'\n  const zoom = mediumZoom('.zoomable-image', {\n    margin: 24, // Space between the image and the edge of the viewport\n    background: 'rgba(0, 0, 0, 0.8)', // Dark overlay background\n    scrollOffset: 40 // Scroll offset to close the zoom\n  });\n\n  // Attach additional images or selectors dynamically\n  zoom.attach('#another-zoomable-image');\n\n  // Listen for events: 'open', 'opened', 'close', 'closed'\n  zoom.on('open', (event) => {\n    console.log('Zoom effect starting for:', event.target);\n    // You can update options after the zoom is opened\n    zoom.update({ background: 'rgba(25, 18, 25, 0.95)' });\n  });\n\n  zoom.on('closed', () => {\n    console.log('Zoom effect finished closing.');\n  });\n\n  // Example of programmatic open (returns a Promise since v1.0.0)\n  // document.getElementById('open-btn')?.addEventListener('click', async () => {\n  //   await zoom.open(document.querySelector('.zoomable-image'));\n  //   console.log('Programmatic zoom opened.');\n  // });\n});\n\n// To make this code runnable, ensure your HTML contains:\n// <img class=\"zoomable-image\" src=\"https://picsum.photos/id/1018/400/300\" alt=\"Forest road\" />\n// <img id=\"another-zoomable-image\" src=\"https://picsum.photos/id/1025/400/300\" alt=\"Pug dog\" />","lang":"typescript","description":"This code initializes `mediumZoom` on elements matching a CSS selector, demonstrates attaching additional elements, sets custom options, and logs events during the zoom lifecycle. It also includes the necessary CSS import."},"warnings":[{"fix":"Review calls to `mediumZoom` methods. For animation methods, use `async/await` or `.then()` to handle their completion. For other methods, adjust chaining as needed.","message":"Version 1.0.0 introduced significant changes where most methods (excluding getters and animation methods) became chainable, and animation methods (`open()`, `close()`, `toggle()`) now return Promises. This may break existing code relying on previous return values or synchronous animation flow.","severity":"breaking","affected_versions":">=1.0.0 <1.1.0"},{"fix":"Ensure you explicitly import the CSS file: `import 'medium-zoom/dist/medium-zoom.css';` in your entry point, or link it via a `<link>` tag in your HTML. Since v1.1.0, a `medium-zoom.pure.css` bundle is also available.","message":"The CSS styles for medium-zoom are not automatically included with the JavaScript. Failing to import the CSS will result in an unstyled zoom overlay and animations, making the feature appear broken or incomplete.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Upgrade to `medium-zoom@1.0.4` or newer. If stuck on older versions, implement conditional rendering or client-side mounting for the zoom functionality within your SSR application.","message":"Earlier versions of medium-zoom (prior to 1.0.4) had limited or no compatibility with Server-Side Rendering (SSR) environments due to direct use of browser-specific `window` objects. This could lead to build failures or runtime errors in SSR frameworks.","severity":"gotcha","affected_versions":"<1.0.4"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure you are using `import mediumZoom from 'medium-zoom';` for ESM setups. If using CommonJS, ensure your build pipeline correctly handles the module export.","cause":"Incorrect import statement or using CommonJS `require` when an ES module environment expects `import`.","error":"Uncaught TypeError: mediumZoom is not a function"},{"fix":"Verify your CSS selector is correct and matches existing `<img>` elements. Wrap your `mediumZoom` initialization in a `DOMContentLoaded` listener or defer it until your images are present in the DOM.","cause":"The `mediumZoom` function was called with a selector that did not match any elements in the DOM, or the elements were not yet available when the script ran.","error":"TypeError: Cannot read properties of null (reading 'style')"},{"fix":"Add `import 'medium-zoom/dist/medium-zoom.css';` to your main JavaScript/TypeScript file or include a `<link>` tag for the CSS in your HTML.","cause":"The required CSS stylesheet for medium-zoom was not loaded or imported.","error":"Zoom effect doesn't appear or the overlay is unstyled"},{"fix":"After dynamically adding new images, use the `zoom.attach(selector)` method on your existing `mediumZoom` instance to make the new images zoomable.","cause":"The `mediumZoom` function was initialized before the dynamic images existed, and the zoom instance was not updated to include them.","error":"Images dynamically added to the DOM are not zoomable."}],"ecosystem":"npm"}