Installation
npm install react-driftkitInteractive Demo
Zoom
3.00×
Lens size
200px
Crosshair
Zoom badge
Hover anywhere on the photo — the lens snaps to your cursor, stays inside the image, and hides when you leave. No activation, no drag; the
target ref wires it to this one element. Zoom into the sails, the hulls, the water taxi wake, or the ripple texture.API Reference
| Prop | Type | Default |
|---|---|---|
active Controlled active state. Omit for uncontrolled. | boolean | — |
defaultActive Uncontrolled initial active state. | boolean | false |
target Scope the lens to one element (product-image-zoom style). When set, the lens only appears over the target, follows the cursor inside it, and hides on leave. Dragging is disabled. Accepts a CSS selector, Element, or React ref. | string | Element | RefObject<Element> | — |
defaultPosition Starting position — 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center' or { x, y } in viewport px. Ignored in target mode. | Corner | { x; y } | 'center' |
zoom Controlled zoom factor. Omit for uncontrolled. | number | — |
defaultZoom Uncontrolled initial zoom factor. | number | 2 |
minZoom Minimum zoom factor. | number | 1.25 |
maxZoom Maximum zoom factor. | number | 10 |
zoomStep Zoom increment applied per wheel notch. | number | 0.25 |
size Lens diameter in pixels. | number | 180 |
behavior Behavior knobs: hotkey, exitOnEscape, wheelToZoom, ignoreSelector. | ZoomLensBehavior | — |
behavior.hotkey Keyboard shortcut to toggle active, e.g. "cmd+shift+z". Supports cmd/meta, ctrl, shift, alt/option + key. | string | — |
behavior.exitOnEscape Deactivate when Escape is pressed. | boolean | true |
behavior.wheelToZoom Allow mouse-wheel over the lens to change zoom. | boolean | true |
behavior.ignoreSelector CSS selector for elements to strip from the magnified clone. Elements with [data-zoom-lens-ignore] are always stripped. | string | — |
on Event handlers: activeChange, zoomChange, positionChange. All optional. | ZoomLensEvents | — |
on.activeChange Fires whenever active toggles — Escape, hotkey, or a setter. | (active: boolean) => void | — |
on.zoomChange Fires when the zoom level changes (wheel, clamp, setZoom). | (zoom: number) => void | — |
on.positionChange Fires while the lens is being dragged. | (pos: { x: number; y: number }) => void | — |
borderColor Rim color of the lens circle. | string | 'rgba(255,255,255,0.9)' |
borderWidth Rim thickness in px. | number | 2 |
showCrosshair Render a 1px crosshair through the lens center. | boolean | true |
showZoomBadge Show the current zoom level in the corner of the lens. | boolean | true |
zIndex z-index for the overlay. | number | 2147483647 |
className CSS class added to the lens circle. | string | '' |
style Inline styles merged into the lens circle. | CSSProperties | {} |
The lens clones a live copy of document.body, debounced on mutations. Mark your own control UI with data-zoom-lens-ignore so it stays out of the magnified view. Known limits: <canvas>, <video>, and <iframe> elements appear blank inside the lens, and position: fixed elements re-anchor to the top-left of the clone.
Code Examples
tsx
import { useState } from 'react';
import { ZoomLens } from 'react-driftkit';
function App() {
const [active, setActive] = useState(false);
return (
<>
<button
data-zoom-lens-ignore
onClick={() => setActive((a) => !a)}
>
{active ? 'Close lens' : 'Zoom in'}
</button>
<ZoomLens
active={active}
behavior={{ hotkey: 'cmd+shift+z' }}
on={{ activeChange: setActive }}
/>
</>
);
}Types
typescript
type ZoomLensTarget =
| string // CSS selector, resolved via querySelector
| Element // a live element
| RefObject<Element | null> // a React ref
| null;
interface ZoomLensProps {
active?: boolean;
defaultActive?: boolean;
// Scope the lens to a single element (product-image-zoom style). When
// set, the lens only appears while the cursor is over the target, follows
// the cursor inside it, and hides on leave. Dragging is disabled in target
// mode. Omit to magnify the whole page and make the lens free-draggable.
target?: ZoomLensTarget;
// Starting position — a corner, "center", or viewport coords. Ignored
// in target mode (lens position is cursor-driven).
defaultPosition?:
| 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center'
| { x: number; y: number };
// Zoom — controlled / uncontrolled, with clamping.
zoom?: number;
defaultZoom?: number; // default 2
minZoom?: number; // default 1.25
maxZoom?: number; // default 10
zoomStep?: number; // default 0.25 per wheel notch
// Lens diameter in px.
size?: number; // default 180
behavior?: {
hotkey?: string; // toggle, e.g. "cmd+shift+z"
exitOnEscape?: boolean; // default true
wheelToZoom?: boolean; // default true
ignoreSelector?: string; // strip from the magnified clone
};
on?: {
activeChange?: (active: boolean) => void;
zoomChange?: (zoom: number) => void;
positionChange?: (pos: { x: number; y: number }) => void;
};
borderColor?: string;
borderWidth?: number;
showCrosshair?: boolean; // default true
showZoomBadge?: boolean; // default true
zIndex?: number; // default 2147483647
className?: string;
style?: CSSProperties;
}Enjoying react-driftkit?
Star the repo on GitHub to help more devs discover it.