react-zoom-image-hover
Version:
This package is for zooming image on hover
213 lines (166 loc) • 8.79 kB
Markdown
# React Zoom Image Hover
A lightweight, performant React component that provides smooth image zoom on hover with customizable zoom behavior, touch support, and accessibility features.
## Features
- 🖼️ **Smooth Zoom Animation** - Smooth image zoom on hover with customizable scale and transition timing
- 📱 **Touch Support** - Works on mobile devices with touch gestures
- ♿ **Accessible** - Uses native `<img>` elements with proper alt text support for screen readers
- ⚡ **Performance Optimized** - Uses React hooks (`useCallback`, `useMemo`) and throttling for optimal performance
- 🎨 **Highly Customizable** - Extensive props for styling and behavior customization
- 🔍 **Smart Mouse Tracking** - Zoom follows mouse position with smooth, throttled updates
- 📦 **TypeScript Support** - Full TypeScript definitions included
- 🎯 **Zero Dependencies** - Only requires React as a peer dependency
- 🌐 **Semantic HTML** - Uses native `<img>` elements for better SEO and accessibility
## Installation
```bash
npm install react-zoom-image-hover
```
or
```bash
yarn add react-zoom-image-hover
```
## Preview

## Basic Usage
```tsx
import Zoom from 'react-zoom-image-hover'
function App() {
return <Zoom src='/path/to/image.jpg' width={400} height={300} zoomScale={2} alt='Product image' />
}
```
## Advanced Usage
```tsx
import Zoom from 'react-zoom-image-hover'
function ProductImage() {
return (
<Zoom
src='https://example.com/product.jpg'
width='100%'
height={500}
zoomScale={2.5}
transitionTime={0.2}
alt='Product detail view'
className='product-image-container'
innerClassName='product-image-inner'
objectFit='cover'
objectPosition='center'
transitionTimingFunction='cubic-bezier(0.4, 0, 0.2, 1)'
enableTouch={true}
throttleDelay={16}
style={{
borderRadius: '8px',
boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
}}
/>
)
}
```
## Props
### Required Props
| Prop | Type | Description |
| -------- | ------------------ | ---------------------------------------------- |
| `src` | `string` | Image source URL |
| `width` | `string \| number` | Container width (CSS value: string or number) |
| `height` | `string \| number` | Container height (CSS value: string or number) |
### Optional Props
| Prop | Type | Default | Description |
| -------------------------- | ---------------------------------------------------------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `className` | `string` | - | Additional CSS class name for the container |
| `innerClassName` | `string` | - | Additional CSS class name for the inner image element |
| `zoomScale` | `number` | `1.5` | Zoom scale multiplier |
| `transitionTime` | `number` | `0.1` | Transition duration in seconds |
| `style` | `CSSProperties` | - | Additional inline styles for the container |
| `alt` | `string` | - | Alt text for accessibility (recommended) |
| `objectFit` | `'contain' \| 'cover' \| 'fill' \| 'none' \| 'scale-down'` | `'contain'` | CSS object-fit value - controls how the image is resized to fit its container. Use `contain` to fit entire image, `cover` to fill container, or `fill` to stretch |
| `objectPosition` | `string` | `'center'` | CSS object-position value - controls the position of the image within its container (e.g., `'center'`, `'top left'`, `'50% 30%'`) |
| `enableTouch` | `boolean` | `true` | Enable touch support for mobile devices |
| `throttleDelay` | `number` | `16` | Throttle delay for mouse movement in milliseconds (~60fps) |
| `transitionTimingFunction` | `string` | `'ease-out'` | CSS transition-timing-function value |
## TypeScript Support
The component is written in TypeScript and includes full type definitions. You can import the props interface:
```tsx
import Zoom, { ZoomProps } from 'react-zoom-image-hover'
const props: ZoomProps = {
src: '/image.jpg',
width: 400,
height: 300,
}
```
## Performance
The component is optimized for performance:
- **Throttled Updates**: Mouse movement updates are throttled (configurable delay) to prevent excessive re-renders while maintaining smooth tracking
- **Memoized Styles**: Style objects are memoized with `useMemo` to avoid unnecessary recalculations
- **Optimized Callbacks**: Event handlers are wrapped in `useCallback` to prevent unnecessary child re-renders
- **Browser Optimization**: Uses `willChange: 'transform'` to hint the browser about upcoming transforms for better rendering performance
- **Efficient Position Calculation**: Mouse position is calculated relative to viewport, avoiding unnecessary scroll calculations
## Accessibility
The component is built with accessibility in mind:
- **Native `<img>` Elements** - Uses semantic HTML for better screen reader support
- **Alt Text Support** - Proper `alt` attribute support for image descriptions
- **Semantic Structure** - Clean, semantic HTML that's easy for assistive technologies to parse
- **Keyboard Friendly** - Works with keyboard navigation (inherits from container)
## Browser Support
Works in all modern browsers that support:
- CSS transforms and transitions
- CSS `object-fit` and `object-position` properties
- React 16+ (tested with React 16.8+ for hooks support)
## Examples
### E-commerce Product Image
```tsx
<Zoom
src='/products/shoe.jpg'
width={600}
height={600}
zoomScale={2}
alt='Nike Air Max 90 - Side view'
className='product-zoom'
transitionTime={0.15}
/>
```
### Gallery with Custom Styling
```tsx
<Zoom
src='/gallery/photo.jpg'
width='100%'
height={400}
zoomScale={3}
alt='Landscape photography'
objectFit='cover'
transitionTimingFunction='ease-in-out'
style={{
borderRadius: '12px',
border: '2px solid #e0e0e0',
}}
/>
```
### Mobile-Optimized
```tsx
<Zoom
src='/mobile-image.jpg'
width={300}
height={300}
zoomScale={2.5}
enableTouch={true}
throttleDelay={20}
alt='Mobile optimized image'
/>
```
### Portrait Image with Custom Positioning
```tsx
<Zoom
src='/portrait-photo.jpg'
width={400}
height={600}
zoomScale={2.5}
objectFit='contain'
objectPosition='center'
alt='Portrait photography'
style={{
borderRadius: '8px',
border: '2px solid #ddd',
}}
/>
```
## License
MIT
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.