hoverzoom-js
Version:
A lightweight, high-performance hover-to-zoom image magnifier plugin with zero dependencies
427 lines (316 loc) β’ 11.2 kB
Markdown
# HoverZoom β Lightweight Non-JQuery Plugin
[](https://github.com/taufiqelrahman/hoverzoom-js/actions)
[](https://github.com/taufiqelrahman/hoverzoom-js/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)



[](https://nodejs.org/)
**HoverZoom** is a lightweight plugin built on **vanilla JavaScript** that allows users to zoom images on hover.
No dependencies, no jQuery, fully optimized for minimal download size and fast performance.
[**Demo & Documentation**](https://hoverzoom-js.vercel.app)
---
## Features
- π **Lightweight** β Only 9.2kB minified (ESM) / 9.4kB (UMD)
- β‘ **High Performance** β Throttled mousemove (60fps), requestAnimationFrame, GPU acceleration
- π¦ **Zero Dependencies** β Pure vanilla JavaScript, no jQuery or other libraries
- π― **Easy Integration** β Works with CDN, npm, or any module bundler
- π **Flexible Zoom Modes** β Inside or outside lens positioning
- π¨ **Visual Effects** β Optional blur and grayscale filters
- πΎ **Smart Caching** β DOM element and image caching for optimal performance
- πΌοΈ **Lazy Loading** β Preloads large images only when needed
- π§Ή **Memory Safe** β Proper cleanup with `destroy()` method
- βΏ **Fully Accessible** β WCAG 2.1 AA compliant with keyboard navigation and screen reader support
- β¨οΈ **Keyboard Friendly** β Tab, Enter/Space, and Escape key support
- π’ **Screen Reader Optimized** β Proper ARIA labels and live regions
- β
**Well Tested** β 95%+ unit test coverage, cross-browser e2e tests
- π **TypeScript** β Written in TypeScript with strict mode and full type definitions
- π **Type Safe** β Strict TypeScript compilation for maximum reliability
---
## Browser Compatibility
Tested in:
- Chrome 139+
- Firefox 69+
- Safari 12+
- Opera 63+
---
## Quick Start
The fastest way to get started:
```html
<html>
<head>
<!-- CSS from CDN -->
<link
rel="stylesheet"
href="https://unpkg.com/hoverzoom-js@latest/dist/hoverzoom.min.css"
/>
</head>
<body>
<!-- Your image -->
<div class="hoverzoom">
<img class="hoverzoom-image" src="your-image.jpg" alt="Zoom image" />
</div>
<!-- JS from CDN -->
<script src="https://unpkg.com/hoverzoom-js@latest/dist/hoverzoom.umd.min.js"></script>
<script>
// Initialize
const hoverZoom = new HoverZoom();
hoverZoom.init();
</script>
</body>
</html>
```
---
## Installation
### 1. Via CDN (No Build Required)
Include the stylesheet in your `<head>`:
```html
<link
rel="stylesheet"
href="https://unpkg.com/hoverzoom-js@latest/dist/hoverzoom.min.css"
/>
```
Include the script before closing `<body>`:
```html
<script src="https://unpkg.com/hoverzoom-js@latest/dist/hoverzoom.umd.min.js"></script>
```
**HTML Structure:**
```html
<!-- Basic usage -->
<div class="hoverzoom">
<img class="hoverzoom-image" src="image.jpg" alt="Zoom this image" />
</div>
<!-- With all options -->
<div class="hoverzoom">
<img class="hoverzoom-image" src="thumbnail.jpg"
data-large-image="full-size.jpg"
<!-- Optional: use different image for zoom -->
data-type="outside"
<!-- 'outside' or 'inside' -->
data-position="right"
<!-- 'right' or 'bottom' (for outside type) -->
data-blur="true"
<!-- Optional: blur effect -->
data-grayscale="true"
<!-- Optional: grayscale effect -->
alt="Product image" >
</div>
```
**Initialize:**
```html
<script>
// Default options
const hoverZoom = new HoverZoom();
hoverZoom.init();
// Or with custom options
const hoverZoom = new HoverZoom({
position: 'right', // 'right' | 'bottom' (for outside type)
type: 'outside', // 'outside' | 'inside'
blur: false, // apply blur filter on hover
grayscale: false, // apply grayscale filter on hover
throttleDelay: 16, // mousemove throttle (ms) - 16ms = ~60fps
});
hoverZoom.init();
// Cleanup when done (e.g., SPA route change)
// hoverZoom.destroy();
</script>
```
---
### 2. Via NPM / Package Manager
**Install:**
```bash
# pnpm (recommended)
pnpm add hoverzoom-js
# npm
npm install hoverzoom-js
# yarn
yarn add hoverzoom-js
```
**JavaScript/TypeScript Usage:**
```typescript
// ES Module (TypeScript or modern JS)
import HoverZoom from 'hoverzoom-js';
import 'hoverzoom-js/style.css';
const hoverZoom = new HoverZoom({
position: 'right',
type: 'outside',
blur: false,
grayscale: false,
});
// Initialize all elements with 'hoverzoom' class
hoverZoom.init();
// Cleanup when component unmounts (important for SPAs)
// hoverZoom.destroy();
```
**React Example:**
```tsx
import { useEffect } from 'react';
import HoverZoom from 'hoverzoom-js';
import 'hoverzoom-js/style.css';
function ProductImage() {
useEffect(() => {
const hoverZoom = new HoverZoom();
hoverZoom.init();
// Cleanup on unmount
return () => hoverZoom.destroy();
}, []);
return (
<div className="hoverzoom">
<img className="hoverzoom-image" src="product.jpg" alt="Product" />
</div>
);
}
```
**Vue Example:**
```vue
<template>
<div class="hoverzoom">
<img class="hoverzoom-image" src="product.jpg" alt="Product" />
</div>
</template>
<script setup>
import { onMounted, onUnmounted } from 'vue';
import HoverZoom from 'hoverzoom-js';
import 'hoverzoom-js/style.css';
let hoverZoom;
onMounted(() => {
hoverZoom = new HoverZoom();
hoverZoom.init();
});
onUnmounted(() => {
hoverZoom?.destroy();
});
</script>
```
---
## Options
| Option | Type | Default | Description |
| ------------- | ------- | --------- | ----------------------------------------------------- |
| position | string | "right" | Position of the zoomed image (right or bottom) |
| type | string | "outside" | Magnifier type (inside or outside) |
| blur | boolean | false | Apply blur filter to the original image |
| grayscale | boolean | false | Apply grayscale filter to the original image |
| throttleDelay | number | 16 | Mousemove throttle delay in ms (16ms = ~60fps) |
| classNames | object | {...} | Custom CSS class names for container, image, elements |
---
## HTML Structure
```html
<div class="hoverzoom">
<img
class="hoverzoom-image"
src="small.jpg"
data-large-image="large.jpg"
data-type="outside"
data-position="right"
data-blur="true"
data-grayscale="false"
/>
</div>
```
---
## Troubleshooting
**Zoom not working?**
- Ensure both CSS and JS files are loaded (check browser console)
- Verify HTML structure: parent with `hoverzoom` class, image with `hoverzoom-image` class
- Call `hoverZoom.init()` after adding elements dynamically
- For SPAs (React/Vue): Make sure to call `destroy()` on unmount to prevent memory leaks
**Image not loading?**
- Check `data-large-image` path is correct (relative to HTML file or absolute URL)
- Open browser DevTools Network tab to verify image loads successfully
- Ensure image CORS settings allow cross-origin loading if using external URLs
**TypeScript errors?**
- Make sure you're using v2.0.0 or later (includes TypeScript definitions)
- Import as: `import HoverZoom from "hoverzoom-js"`
- Check [src/HoverZoom.d.ts](src/HoverZoom.d.ts) for type definitions
---
## π€ Contributing
We β€οΈ contributions!
- Check out good first issues here
- Fork the repo & create a branch:
```bash
git checkout -b feature/amazing-feature
```
- Commit & push your changes:
```bash
git commit -m "Add amazing feature"
git push origin feature/amazing-feature
```
- Open a Pull Request to main.
### Guidelines
- Follow TypeScript best practices (source is in `src/HoverZoom.ts`)
- Write tests for new features (unit tests in Jest, e2e in Playwright)
- Run `pnpm run build` to compile TypeScript and test changes
- Ensure all tests pass: `pnpm run test:all`
- Follow existing code style and conventions
- Use conventional commit messages
- Keep code clean & formatted
βΈ»
## π Performance
HoverZoom is optimized for maximum performance:
- **Throttled Events**: Mousemove events throttled to 60fps by default (configurable)
- **GPU Acceleration**: Uses `translate3d` for hardware-accelerated transforms
- **Smart Caching**: DOM elements and images cached to minimize queries
- **Lazy Loading**: Large images preloaded only when needed
- **Minimal Reflows**: Dimensions cached to avoid repeated layout calculations
- **RequestAnimationFrame**: Smooth animations synced with browser repaint cycle
## π§ͺ Testing
```bash
# Unit tests (Jest)
pnpm test
pnpm run test:coverage # With coverage report
# E2E tests (Playwright)
pnpm run test:e2e
pnpm run test:e2e:ui # With UI mode
# All tests
pnpm run test:all
```
See [TESTING.md](./TESTING.md) for detailed testing documentation.
## βΏ Accessibility
HoverZoom is built with accessibility in mind and supports:
### Keyboard Navigation
- **Tab** - Focus on zoomable images
- **Enter / Space** - Toggle zoom on/off
- **Escape** - Deactivate zoom
- **Tab (while zoomed)** - Deactivate and move to next element
### Screen Reader Support
- Full ARIA attributes support
- Descriptive labels for all interactive elements
- Live region announcements for state changes
- Proper semantic HTML structure
- Tested with NVDA, JAWS, and VoiceOver
### Standards Compliance
- WCAG 2.1 Level AA compliant
- Section 508 compliant
- ARIA 1.2 specification
See [SCREEN_READER_TESTING.md](./SCREEN_READER_TESTING.md) for detailed accessibility testing guide.
## π¦ Deployment
```bash
# Build for production (compiles TypeScript)
pnpm run build:all
# Verify package contents
pnpm run verify
# Deploy to npm (automated)
pnpm run deploy
```
See [DEPLOYMENT.md](./DEPLOYMENT.md) for complete deployment guide.
## π οΈ Development
The project is written in **TypeScript** for better type safety and developer experience:
- **Source**: `src/HoverZoom.ts` (TypeScript)
- **Build**: Compiled to JavaScript via Rollup + TypeScript plugin
- **Output**: `dist/*.js` (ES Module & UMD formats)
- **Types**: Type definitions auto-generated during build
```bash
# Install dependencies
pnpm install
# Development workflow
pnpm run dev # Build + start dev server
pnpm run build # Compile TypeScript + build all
pnpm run test:watch # Run tests in watch mode
```
See [BUILD_WORKFLOW.md](./BUILD_WORKFLOW.md) for detailed build documentation.
## π License
MIT License
## π Bug Reports & Feature Requests
Submit via [GitHub Issues](https://github.com/taufiqelrahman/hoverzoom-js/issues).
βΈ»
Made with β€οΈ for building a lightweight, high-performance image zoom plugin.