Skip to content

resizable

Resize an element. By default the library creates eight handles — one per edge and corner — inside the target.

import { resizable } from '@arshad-shah/detent';
import '@arshad-shah/detent/styles.css';
resizable(element, { minWidth: 80, minHeight: 60 });

Grab any edge or corner of the panel below.

All eight handles

Pulling the top or left edge moves the element as well as sizing it — the edge you grabbed follows the pointer, so the opposite edge stays put. The offset is derived from the final clamped size, so hitting a minimum never causes drift.

aspectRatio keeps width and height in proportion. true holds the element’s starting ratio; a number sets one explicitly. On a corner handle, whichever axis you push harder leads.

aspectRatio: 16 / 9, bottom-right handle only
Option Type Default What it does
handles HandleName[] | Record<HandleName, string | HTMLElement> all eight Which edges and corners can be grabbed.
minWidth, minHeight number 16 Smallest size a resize will produce.
maxWidth, maxHeight number Infinity Largest size a resize will produce.
aspectRatio boolean | number true keeps the starting ratio; a number sets one.
grid number | [number, number] Snap the size to a grid, in pixels.
bounds 'parent' | 'window' | Element | Box | null null Keep the element inside this area.
disabled boolean false Keep the binding but stop responding.

HandleName is one of 'n', 'e', 's', 'w', 'ne', 'nw', 'se', 'sw'. Both HandleName and HandleSpec are exported, so you can type a helper that builds a handle list.

As an array, the library creates eight <span> children. As an object, it binds to elements you already have:

resizable(card, {
handles: { se: '.card-corner', e: '.card-edge' },
});

Use the object form when appending children would disturb your component — framework rendering, :last-child and :nth-child rules, or code that walks element.children. With supplied handles the library also leaves the target’s position alone.

resizable(element, {
onStart(event) {}, // return false to refuse
onResize(event) {},
onEnd(event, cancelled) {},
});

Each receives { element, width, height, handle, event, cancel() }, where handle is the HandleName being dragged.

handle.setDisabled(true);
handle.destroy();

destroy() removes only the handles the library created. Elements you supplied are given back as they were found.

Bounds become a size ceiling. With bounds set, the element runs out of room rather than escaping its container.

Minimums win over ratios. When aspectRatio and the size limits conflict, the limits are honoured — the less surprising of the two failures.

Resizing from the top or left moves the element as well as sizing it, and the offset is derived from the final clamped size, so hitting a minimum never causes drift.