Resizable Split Layouts in JavaScript – resizable-panes-js

Category: Javascript , Layout | September 30, 2026
Authorvimalsharmazones
Last UpdateSeptember 30, 2026
LicenseMIT
Views0 views
Resizable Split Layouts in JavaScript – resizable-panes-js

resizable-panes-js is a JavaScript library for creating draggable split-pane layouts with multiple resizable panels.

It supports ratio or pixel sizing, per-pane size limits, nested layouts, pane visibility controls, and persistent layout state.

Features

  • Horizontal and vertical split layouts.
  • Ratio and pixel sizing modes.
  • Mouse and touch resizing.
  • Per-pane minimum and maximum size limits.
  • Custom normal and active resizer classes.
  • Configurable resizer size and pointer detection radius.
  • Programmatic pane sizing and visibility control.
  • Nested resizable pane groups.
  • Persistent pane sizes and visibility through a storage API.
  • Resize, visibility, and size-limit callbacks.

How To Use It

Installation

Install the package from npm or Yarn.

npm install resizable-panes-js
yarn add resizable-panes-js

Basic Usage

Each pane needs a unique ID. Place a resizer after every pane except the last one. The resizer ID uses resizer- followed by the ID of the preceding pane.

This example uses ratio values for the initial layout and pixel values for the pane limits. The ratio values 2, 5, and 3 define the relative share of the available space.

<div id="workspace">
  <aside id="navigation" class="pane">
    Navigation
  </aside>
  <div id="resizer-navigation"></div>
  <main id="editor" class="pane">
    Editor
  </main>
  <div id="resizer-editor"></div>
  <aside id="preview" class="pane">
    Preview
  </aside>
</div>
#workspace {
  display: flex;
  width: 100%;
  height: 320px;
}
.pane {
  flex-shrink: 0;
  overflow: hidden;
}
.resize-handle {
  box-sizing: border-box;
  flex-shrink: 0;
  background: #cbd5e1;
  cursor: col-resize;
}
.resize-handle-active {
  background: #64748b;
}
import resizablePanes from "resizable-panes-js";
const [layoutApi, refreshLayout, clearLayout] = resizablePanes({
  uniqueId: "workspace",
  vertical: true,
  unit: "ratio",
  minMaxUnit: "pixel",
  resizerSize: 6,
  resizerClass: "resize-handle",
  activeResizerClass: "resize-handle-active",
  panes: [
    {
      id: "navigation",
      size: 2,
      minSize: 160,
      maxSize: 320
    },
    {
      id: "editor",
      size: 5,
      minSize: 280
    },
    {
      id: "preview",
      size: 3,
      minSize: 180,
      maxSize: 420
    }
  ]
});

Configuration Options

  • uniqueId (string, required): ID of the resizable container.
  • vertical (boolean, default false): Set to true for side-by-side panes that resize by width. The default creates stacked panes that resize by height.
  • unit ('ratio' | 'pixel', default 'ratio'): Defines how pane size values are interpreted. Ratio values act as relative weights across the visible panes.
  • minMaxUnit ('ratio' | 'pixel', default matches unit): Defines the unit used by minSize and maxSize. Set it to 'pixel' when ratio-sized panes need fixed pixel limits.
  • detectionRadius (number, default 6): Extends the pointer detection region around each resizer.
  • visibility (Object, default {}): Initial boolean visibility map keyed by pane ID.
  • storageApi (Object): Storage object used to persist pane data. localStorage, sessionStorage, or another object with a compatible storage API can be used.
  • resizerClass (string): Class or space-delimited classes applied to resizers in their normal state.
  • activeResizerClass (string): Class or classes applied while a resizer is active.
  • resizerSize (number, default 2): Default resizer size in pixels.
  • onResize (function): Receives the pane size map during resizing.
  • onResizeStop (function): Receives the pane size map after resizing stops.
  • onChangeVisibility (function): Receives the visibility map after pane visibility changes.
  • onMinSize (function): Runs when a pane reaches its minimum size.
  • onMaxSize (function): Runs when a pane reaches its maximum size.
  • onNormalSize (function): Runs when a pane returns to its normal size range.
  • panes (IPane[], required): Array containing the pane definitions.

Pane Options

  • id (string, required): ID of the pane DOM element.
  • size (number, required): Initial pane size or ratio weight, according to unit.
  • maxSize (number, default Infinity): Maximum pane size.
  • minSize (number, default 0): Minimum pane size.
  • detectionRadius (number, default 6): Detection radius for the resizer attached to this pane.
  • resizerSize (number): Resizer size override for this pane.
  • resizerClass (string): Normal-state class override for this pane’s resizer.
  • activeResizerClass (string): Active-state class override for this pane’s resizer.
  • onMinSize (function): Runs when this pane reaches its minimum size.
  • onMaxSize (function): Runs when this pane reaches its maximum size.
  • onNormalSize (function): Runs when this pane returns to its normal size range.

Persist Pane Sizes And Visibility

Pass a storage object through storageApi when the browser should retain pane sizes and visibility.

resizablePanes({
  uniqueId: "workspace",
  vertical: true,
  unit: "ratio",
  storageApi: localStorage,
  panes: [
    { id: "navigation", size: 2 },
    { id: "editor", size: 5 },
    { id: "preview", size: 3 }
  ]
});

Returned API And Lifecycle Functions

resizablePanes() returns the API object followed by two listener-management functions.

const [
  resizableApi,
  refreshResizable,
  clearResizable
] = resizablePanes(config);

The package exports RATIO, TOP_FIRST, and BUTTOM_FIRST for the optional resize behavior parameter.

import resizablePanes, {
  RATIO,
  TOP_FIRST,
  BUTTOM_FIRST
} from "resizable-panes-js";

API Methods

restore()

Restores the initial layout state.

resizableApi.restore();

setSize(paneId, size, behavior?)

Sets a pane size while respecting its size limits and the constraints of the other panes.

resizableApi.setSize("editor", 420);
resizableApi.setSize(
  "editor",
  420,
  TOP_FIRST
);

setSizeRatio(paneId, ratio, behavior?)

Sets the pane to a ratio from 0 to 1. A ratio of 1 corresponds to the total size of the visible panes.

resizableApi.setSizeRatio("preview", 0.3);

setVisibilities(map)

Changes pane visibility from a boolean map keyed by pane ID.

resizableApi.setVisibilities({
  navigation: true,
  editor: true,
  preview: false
});

getSizes()

Returns the current pane sizes keyed by pane ID.

const sizes = resizableApi.getSizes();

getVisibilities()

Returns the current boolean visibility map.

const visibility = resizableApi.getVisibilities();

getState()

Returns the current state of each pane, including its size, visibility, default minimum size, and default maximum size.

const state = resizableApi.getState();

Lifecycle Functions

Call refreshResizable() after application code replaces or restructures the pane DOM and the resizer detection listeners need to be attached again.

refreshResizable();

Call clearResizable() when the layout is removed and its registered resize listeners should be cleared.

clearResizable();

Callbacks

Callbacks can be defined for live resizing, completed resizing, visibility changes, and transitions into minimum, maximum, or normal size states.

resizablePanes({
  uniqueId: "workspace",
  vertical: true,
  unit: "ratio",
  onResize(sizes) {
    console.log("Current sizes:", sizes);
  },
  onResizeStop(sizes) {
    console.log("Final sizes:", sizes);
  },
  onChangeVisibility(visibility) {
    console.log("Visibility:", visibility);
  },
  onMinSize(id, size) {
    console.log(id, "reached its minimum size:", size);
  },
  onMaxSize(id, size) {
    console.log(id, "reached its maximum size:", size);
  },
  onNormalSize(id) {
    console.log(id, "returned to its normal size range");
  },
  panes: [
    { id: "navigation", size: 2 },
    { id: "editor", size: 5 },
    { id: "preview", size: 3 }
  ]
});

Nested Resizable Panes

Give each nested container and pane its own ID. Initialize the parent and child layouts independently.

<div id="outer-layout">
  <div id="sidebar" class="pane">
    <div id="inner-layout">
      <div id="top-panel" class="pane">Top</div>
      <div id="resizer-top-panel"></div>
      <div id="bottom-panel" class="pane">Bottom</div>
    </div>
  </div>
  <div id="resizer-sidebar"></div>
  <div id="main-panel" class="pane">
    Main
  </div>
</div>
resizablePanes({
  uniqueId: "outer-layout",
  vertical: true,
  unit: "ratio",
  panes: [
    { id: "sidebar", size: 3 },
    { id: "main-panel", size: 7 }
  ]
});
resizablePanes({
  uniqueId: "inner-layout",
  vertical: false,
  unit: "ratio",
  panes: [
    { id: "top-panel", size: 1 },
    { id: "bottom-panel", size: 1 }
  ]
});

Alternatives And Related Resources

You Might Be Interested In:


Leave a Reply