react-svg-pan-zoom and react-zoom-pan-pinch are both React libraries designed to add interactive zooming, panning, and fitting capabilities to content, but they target different use cases and underlying technologies. react-svg-pan-zoom is a specialized wrapper built exclusively for SVG elements, offering precise control over vector graphics, coordinate systems, and SVG-specific events. It is ideal for technical diagrams, maps, and data visualizations where maintaining vector fidelity is critical. react-zoom-pan-pinch, on the other hand, is a general-purpose solution that works with any HTML content (images, divs, canvases, or mixed DOM). It focuses on touch gestures, pinch-to-zoom on mobile devices, and smooth transitions for raster images or complex DOM structures, making it the go-to choice for image galleries, photo viewers, and interactive maps built with standard HTML elements.
When building interactive interfaces that require users to explore large content areasโwhether it's a detailed engineering schematic or a high-resolution photographโyou need robust tools to handle zooming and panning. react-svg-pan-zoom and react-zoom-pan-pinch solve this problem but take fundamentally different architectural approaches based on the content type they target. Let's dive into how they differ in implementation, capabilities, and real-world application.
The most critical distinction lies in what these libraries can actually wrap. This decision often dictates your entire component structure.
react-svg-pan-zoom is built exclusively for SVG. It expects a single <svg> element as its child. It does not work with <img> tags, <div> containers, or Canvas elements. This specialization allows it to expose the underlying SVG coordinate system directly to your React code.
import ReactSVGPanZoom from 'react-svg-pan-zoom';
function DiagramViewer() {
return (
<ReactSVGPanZoom
width={800}
height={600}
tool="auto"
>
<svg width="800" height="600">
<rect x="10" y="10" width="100" height="100" fill="blue" />
{/* Only SVG elements allowed here */}
</svg>
</ReactSVGPanZoom>
);
}
react-zoom-pan-pinch is content-agnostic. It wraps a TransformWrapper around any HTML structure. You can zoom into an image, a complex div layout, a canvas, or even a mix of text and media. This makes it far more flexible for general-purpose UI patterns.
import { TransformWrapper, TransformComponent } from 'react-zoom-pan-pinch';
function ImageViewer() {
return (
<TransformWrapper>
<TransformComponent>
<img src="/high-res-photo.jpg" alt="Zoomable content" />
{/* Can also contain divs, text, or other HTML */}
<div style={{ position: 'absolute', top: 10, left: 10 }}>Overlay Text</div>
</TransformComponent>
</TransformWrapper>
);
}
How users interact with the content differs significantly between the two, reflecting their intended environments (desktop-heavy technical tools vs. mobile-friendly viewers).
react-svg-pan-zoom uses a "tool" based interaction model. You explicitly set the current tool mode via props or methods: pan, zoom, select, or auto. This is excellent for desktop applications where users might switch between dragging the canvas and selecting elements within it.
function TechnicalDiagram() {
const [tool, setTool] = useState('pan');
return (
<div>
<button onClick={() => setTool('pan')}>Pan Mode</button>
<button onClick={() => setTool('select')}>Select Mode</button>
<ReactSVGPanZoom
tool={tool}
width={800}
height={600}
>
<svg><!-- SVG content --></svg>
</ReactSVGPanZoom>
</div>
);
}
react-zoom-pan-pinch relies on natural gestures. It automatically detects mouse drags, wheel scrolling, and touch pinch events without requiring mode switches. It includes built-in support for double-click-to-zoom and momentum scrolling, which feels native on mobile devices.
function MobileGallery() {
return (
<TransformWrapper
doubleClick={{ mode: 'zoomIn' }}
wheel={{ step: 0.1 }}
pinch={{ step: 1 }}
>
<TransformComponent>
<img src="/gallery-image.jpg" alt="Pinch to zoom" />
</TransformComponent>
</TransformWrapper>
);
}
For developers building complex applications, the ability to programmatically control the view and map coordinates is often a dealbreaker.
react-svg-pan-zoom excels here because it understands the SVG coordinate space. You can easily convert a screen click (client coordinates) into an SVG point (user space coordinates), which is vital for adding markers or handling clicks on specific vector paths. It also provides a rich ref API to control the view matrix directly.
function MapWithMarkers({ svgRef }) {
const handleScreenClick = (event) => {
// Get the SVG point from the screen event
const svgPoint = svgRef.current.getPoint(event);
console.log('SVG Coordinates:', svgPoint.x, svgPoint.y);
// Programmatically center the view on a specific SVG coordinate
svgRef.current.fitSelection(100, 100, 200);
};
return (
<ReactSVGPanZoom ref={svgRef} onClick={handleScreenClick}>
<svg><!-- content --></svg>
</ReactSVGPanZoom>
);
}
react-zoom-pan-pinch provides control methods via its context hook, but they operate in generic scale and offset values (pixels). While you can center the view or reset the transform, mapping a click back to a specific point inside a raster image requires manual math based on the current scale and position state.
import { useTransformContext } from 'react-zoom-pan-pinch';
function CustomControls() {
const { setTransform, centerView, resetTransform } = useTransformContext();
const zoomToCenter = () => {
// Zooms to scale 2 at the center of the container
centerView(2, 500);
};
const reset = () => {
resetTransform();
};
return (
<div>
<button onClick={zoomToCenter}>Zoom In</button>
<button onClick={reset}>Reset View</button>
</div>
);
}
Styling the viewer container and the content inside follows different patterns due to their DOM structures.
react-svg-pan-zoom injects its own inline styles for the viewer container to manage overflow and cursor states. Customizing the look often requires overriding these inline styles or using the provided props for cursor types. The content inside remains pure SVG, so you style it using standard CSS classes or SVG attributes.
<ReactSVGPanZoom
style={{ border: '1px solid #ccc' }}
background="#f0f0f0"
detectAuto={false}
// Custom cursors
toolPanCursor="grab"
toolPanActiveCursor="grabbing"
>
<svg className="my-custom-svg">
<rect className="highlighted-part" />
</svg>
</ReactSVGPanZoom>
react-zoom-pan-pinch gives you full control via standard CSS. The wrapper and component are just divs, so you can apply flexbox, grid, or absolute positioning to your content easily. It also supports custom HTML controls rendered inside the transform scope, which move with the zoomed content.
<TransformWrapper
initialScale={1}
limitToBounds={false}
>
{({ zoomIn, zoomOut }) => (
<>
<TransformComponent>
<div className="relative w-full h-full">
<img src="/map.png" />
{/* This label moves and scales with the image */}
<div className="absolute top-10 left-10 bg-white p-2">
Location A
</div>
</div>
</TransformComponent>
{/* These controls stay fixed outside the zoom area */}
<div className="controls">
<button onClick={() => zoomIn()}>+</button>
<button onClick={() => zoomOut()}>-</button>
</div>
</>
)}
</TransformWrapper>
Despite their differences, both libraries solve the core problem of navigating large content spaces effectively.
Both libraries provide smooth, performant transformations for moving and scaling content. They handle the heavy lifting of matrix math so you don't have to.
// Both allow limiting the zoom range
// react-svg-pan-zoom
<ReactSVGPanZoom minScale={0.5} maxScale={5} />
// react-zoom-pan-pinch
<TransformWrapper minScale={0.5} maxScale={5} />
Both are written as React components and follow standard React patterns for props and refs. They update efficiently when props change and clean up event listeners on unmount.
// Both can be controlled via refs for imperative actions
const svgRef = useRef();
const transformRef = useRef();
// Usage in effect hooks or event handlers is standard React
useEffect(() => {
if (svgRef.current) svgRef.current.reset();
if (transformRef.current) transformRef.current.resetTransform();
}, []);
Both offer options to prevent users from panning the content completely off-screen, ensuring a better user experience by keeping the content visible.
// react-svg-pan-zoom
<ReactSVGPanZoom detectAuto={true} />
// react-zoom-pan-pinch
<TransformWrapper limitToBounds={true} />
| Feature | react-svg-pan-zoom | react-zoom-pan-pinch |
|---|---|---|
| Content Type | SVG Only | Any HTML (Img, Div, Canvas) |
| Interaction | Tool-based (Pan/Select/Zoom modes) | Gesture-based (Pinch, Wheel, Drag) |
| Mobile Support | Basic touch support | Excellent pinch-to-zoom & momentum |
| Coordinates | Direct SVG coordinate mapping | Pixel-based scale/offset |
| Dependencies | Depends on svg-pan-zoom | Zero dependencies |
| Use Case | Diagrams, CAD, Vector Maps | Photo Viewers, Mobile Maps, UI Zoom |
react-svg-pan-zoom is the specialist tool ๐ ๏ธ. If you are building a technical application like a circuit board editor, a floor plan viewer, or a data visualization dashboard where the content is strictly SVG, this is your best choice. Its ability to translate screen clicks into SVG coordinates saves you from writing complex math and ensures your vector graphics remain crisp at any zoom level.
react-zoom-pan-pinch is the universal adapter ๐. If you need to support mobile users with pinch gestures, or if your content includes photos, mixed HTML layouts, or canvas elements, this library provides a smoother, more native feel. It requires less setup for common interactions and adapts easily to responsive designs.
Final Thought: The choice isn't about which library is "better," but which data format you are presenting. Stick to SVG? Go with react-svg-pan-zoom. Dealing with pixels, photos, or general DOM? react-zoom-pan-pinch will save you time and provide a better user experience on touch devices.
Choose react-svg-pan-zoom if your primary content is SVG and you need deep integration with the SVG coordinate system. It is the best fit for engineering diagrams, floor plans, or data charts where you must map screen clicks back to precise SVG coordinates or manipulate specific SVG elements programmatically. Avoid this package if you need to zoom into raster images or standard HTML divs, as it strictly requires an SVG root element.
Choose react-zoom-pan-pinch if you need a versatile solution that handles images, HTML content, or mixed media with excellent mobile touch support. It is ideal for building image viewers, product zoom features, or interactive maps where pinch gestures and smooth momentum scrolling are priorities. Select this package when your content is not limited to SVG or when you need a lightweight, dependency-free implementation that works seamlessly across desktop and mobile touchscreens.
react-svg-pan-zoom is a React component that adds pan and zoom features to the SVG images. It helps to display big SVG images in a small space.
available at http://chrvadala.github.io/react-svg-pan-zoom/
This component can work in four different modes depending on the selected tool:
npm install --save react-svg-pan-zoom
yarn add react-svg-pan-zoom
<script src="https://unpkg.com/prop-types@15/prop-types.js"></script>
<script src="https://unpkg.com/react-svg-pan-zoom@3"></script>
<ReactSVGPanZoom>.<UncontrolledReactSVGPanZoom>.setPointOnViewerCenter, reset methods and className, style propsauto, improves default toolbarpreventPanOutside and scaleFactor propsminiatureBackground, miniatureHeight, Minor improvements & fixdisableDoubleClickZoomWithToolAutoscaleFactorOnWheel, Upgrades depsscaleFactorMax, scaleFactorMin props (#71), Upgrades depsonPan and onZoom callbacks, Upgrade deps, Fixes boundaries featuretoolbarProps.SVGAlignX and toolbarProps.SVGAlignY props. Adds alignment configuration in fitToViewer(SVGAlignX = "left", SVGAlignY = "top") method (#120). Upgrades deps.<UncontrolledReactSVGPanZoom /> component and makes <ReactSVGPanZoom> a stateless component (except for some optimizations); Moves props related to miniature and toolbar, respectively into the miniatureProp and toolbarProp props. Migration guide is available here.fitToViewer method #167, adds activeToolColor property #168, upgrades deps