mrkeyoor.com_
Sat 08 Aug 21:58 UTC
npmWeb Frontendupdated 08 Aug 2026

@visx/responsive

@visx/responsive is the measurement and SVG-scaling package in Airbnb's low-level visx chart toolkit. Version 4 provides useParentSize and ParentSize for ResizeObserver-based container dimensions, useScreenSize for debounced window dimensions, higher-order component equivalents for older React code, and ScaleSVG for fitting a fixed viewBox into available width. It does not draw charts itself; it supplies width, height, top, left, refs, and resize behavior that you pass into chart primitives from other visx packages or your own SVG components.

Verdict

The right measurement glue for teams already composing charts from visx primitives, and v4 removes lodash while improving refs and flex or grid behavior. Skip it if all you need is generic element measurement or if you expect one package to provide a complete responsive chart.

API stability3/5The core concepts have lasted across visx versions, but v4 is a real migration: React 18 or 19 is required, deep imports are blocked by an exports map, modern browser targets replace IE11, ParentSize has a two-div structure, and useParentSize changed parentRef from a ref object to a callback while exposing node separately. The migration guide documents each change well, yet consumers with CSS, tests, or ref access must update.
Docs4/5The package README documents every hook, higher-order component, component, default initial size, 300 ms debounce, leading-call behavior, ignored dimensions, and ResizeObserver injection with TypeScript examples. The root migration guide adds exact v4 ref, wrapper, peer, exports, and browser changes. Practical layout failures such as unresolved percentage heights and hydration placeholders deserve more prominent examples.
Maintenance5/5Version 4.0.0 was published on 2026-06-11, and GitHub reports a repository push on 2026-06-22. The release removed lodash, fixed measurement loops in flex and grid layouts, added external-ref support, modernized ESM packaging, and published migration guidance. The monorepo reports 146 open issues and PRs, but active releases, tests, and detailed alpha history show sustained work across a large toolkit.
Ecosystem5/5The npm downloads endpoint reports 3,840,641 downloads in its last-week window, and the visx monorepo has 20,999 GitHub stars. The package integrates directly with visx's widely used shape, scale, axis, tooltip, and XYChart packages, publishes ESM, CommonJS, and types, and works with React 18 or 19. Its value is strongest inside visx, while generic measurement users have focused alternatives.

Use it if

  • You already build charts from visx primitives and need a supported way to feed them measured container dimensions
  • You need a ResizeObserver hook with initial size, debounce, ignored-dimension, polyfill, and external-ref options
  • You want one responsive measurement API for both hook-based and older higher-order-component React code
  • A fixed-coordinate SVG only needs viewBox scaling and preserving its aspect ratio is acceptable
Skip it if

Setup reality

Install @visx/responsive alongside React 18 or 19. It has no runtime dependencies, but React is a peer and @types/react 18 or 19 is an optional peer that TypeScript applications should install at the matching major. No stylesheet, provider, credentials, native build, or configuration file is needed. The main setup work is layout. ParentSize defaults its outer wrapper to width: 100%, height: 100%, and position: relative, so every ancestor that contributes percentage height must have a resolved height or the measured chart can be zero pixels tall. Version 4 renders an outer div plus an absolutely positioned measurement div to prevent flex and grid feedback loops; CSS selectors and tests written for the v3 one-wrapper shape must change. useParentSize now returns a callback parentRef and the measured node separately. Code that read parentRef.current must use node, and code that needs its own ref should pass externalRef. Measurements start at width and height zero unless initialSize is provided, then update in an effect through ResizeObserver and requestAnimationFrame. That avoids browser access during render but can produce an empty server render, a placeholder jump, or a hydration-sensitive chart if zero-size output differs structurally. The default 300 ms debounce fires on the leading edge, then on the trailing edge only when more measurements arrive. Tune it for animation and dashboard resizing. Older browsers, test environments, and some non-DOM runtimes need an injected ResizeObserver implementation. useScreenSize reads window in an effect and has the same zero-size and debounce story. ScaleSVG requires explicit design width and height and creates its own div and svg; it scales strokes, text, and marks together but does not recalculate ticks or labels. Deep imports are blocked by the v4 exports map, so import every supported symbol from @visx/responsive.

Patterns

Render a chart with measured parent dimensionsmeasure-with-parent-size

import { ParentSize } from '@visx/responsive';

<div style={{ width: '100%', height: 360 }}>
  <ParentSize>
    {({ width, height }) => (
      width > 0 && height > 0 ? <Chart width={width} height={height} /> : null
    )}
  </ParentSize>
</div>

Give the ancestor a resolved height. ParentSize uses height: 100%, which cannot create height when its containing block is auto-sized.

Attach useParentSize directly to a containermeasure-with-hook

import { useParentSize } from '@visx/responsive';

function ResponsiveChart() {
  const { parentRef, width, height } = useParentSize();
  return (
    <div ref={parentRef} style={{ width: '100%', height: 320 }}>
      {width > 0 && height > 0 && <Chart width={width} height={height} />}
    </div>
  );
}

In v4 parentRef is a callback ref, not an object with .current. The measured element is also available as node.

Render a useful initial chart sizeprovide-initial-size

const { parentRef, width, height } = useParentSize({
  initialSize: { width: 640, height: 360 },
});

Initial size is used before the first browser measurement. Choose a stable placeholder size when server rendering to reduce layout jumps.

Make resizing feel more immediatetune-resize-debounce

const size = useParentSize({
  debounceTime: 50,
  enableDebounceLeadingCall: true,
});

The default delay is 300 ms. A shorter value feels smoother but can cause more React renders during continuous resizing.

Supply a ResizeObserver implementationinject-resize-observer

import { ResizeObserver } from '@juggle/resize-observer';
import { useParentSize } from '@visx/responsive';

const size = useParentSize({
  resizeObserverPolyfill: ResizeObserver,
});

@juggle/resize-observer is not a runtime dependency of the package. Install the polyfill yourself when the platform lacks the native API.

Receive the measured node through your own refforward-external-ref

const containerRef = useRef<HTMLDivElement>(null);
const { parentRef, node, width } = useParentSize<HTMLDivElement>({
  externalRef: containerRef,
});

return <div ref={parentRef}>{width > 0 && <Chart width={width} />}</div>;

v4 forwards the same node to externalRef and returns it as node, avoiding a second wrapper used only to merge refs.

Update only when width or height changesignore-position-changes

const size = useParentSize({
  ignoreDimensions: ['top', 'left'],
});

Ignored dimensions do not trigger state replacement when they are the only changed values. The incoming full measurement is used when a non-ignored value also changes.

Adapt a full-screen visualizationmeasure-screen-size

import { useScreenSize } from '@visx/responsive';

function FullScreenChart() {
  const { width, height } = useScreenSize({
    initialSize: { width: 1280, height: 720 },
    debounceTime: 100,
  });
  return <Chart width={width} height={height} />;
}

useScreenSize measures window.innerWidth and innerHeight, not a component. Use useParentSize for dashboards and nested layouts.

Scale a fixed-coordinate SVGscale-fixed-svg

import { ScaleSVG } from '@visx/responsive';

<ScaleSVG width={800} height={400}>
  <ChartMarks width={800} height={400} />
</ScaleSVG>

ScaleSVG sets viewBox='0 0 800 400' and stretches the SVG to its wrapper. It does not recalculate tick density or font size.

Fill the container by cropping the viewBoxcontrol-svg-cropping

<ScaleSVG
  width={800}
  height={400}
  preserveAspectRatio="xMidYMid slice"
>
  <ChartMarks width={800} height={400} />
</ScaleSVG>

slice fills the viewport and can crop edges. The default xMinYMin meet preserves the whole viewBox and may leave unused space.

Measure a legacy class-compatible chart with an HOCwrap-class-component

import { withParentSize } from '@visx/responsive';

function Chart({ parentWidth, parentHeight }) {
  if (parentWidth == null || parentHeight == null) return null;
  return <svg width={parentWidth} height={parentHeight} />;
}

export default withParentSize(Chart);

The higher-order component exists for older component patterns. Prefer useParentSize in new function components.

Override a ParentSize measurementtrigger-manual-resize

<ParentSize initialSize={{ width: 400, height: 240 }}>
  {({ width, height, resize }) => (
    <>
      <Chart width={width} height={height} />
      <button onClick={() => resize({ width: 800, height, top: 0, left: 0 })}>
        Use wide layout
      </button>
    </>
  )}
</ParentSize>

resize goes through the configured debounce and updates all four state fields. A later ResizeObserver notification can replace the manual dimensions.

Alternatives

PackageRegistryPick it when
react-use-measurenpmYou want a general-purpose bounds hook with ResizeObserver outside the visx ecosystem
use-resize-observernpmYou want a focused hook with configurable rounding, callbacks, and observed box selection
react-resize-detectornpmYou prefer a component or hook API for general React element-resize detection
rechartsnpmYou want a higher-level chart library whose ResponsiveContainer and chart components come together