Modern workspace with split-panel interface and a red maine coon cat

React Split Pane v3: The Classic Layout Splitter Gets a Modern Makeover

The Orange Cat
The Orange Cat

If you have been building React apps for a while, chances are you have crossed paths with React Split Pane. For years it was the go-to library for resizable split layouts -- code editors, file browsers, dashboard panels, you name it. But that original v0.1.x codebase was showing its age: class components, no TypeScript, limited to exactly two panes, and no accessibility story to speak of.

That all changed with react-split-pane v3. Released in late 2025 and actively maintained into 2026, version 3 is a complete ground-up rewrite. Same package name, entirely new internals. Let us walk through what is new, what broke, and how to upgrade.

Everything Old Is New Again

The headline features of v3 read like a wishlist from the community:

  • Hooks-based architecture replacing class components entirely
  • Full TypeScript support with types included out of the box
  • React 17, 18, and 19 compatibility so you are covered no matter which version you are on
  • Accessibility built in with keyboard navigation, ARIA attributes, and screen reader support
  • Multi-pane layouts supporting two or more panes in a single SplitPane
  • Zero runtime dependencies at under 5KB gzipped
  • Snap points for snapping dividers to predefined positions
  • Built-in persistence hook for saving layouts to localStorage or sessionStorage
  • CSS custom properties for easy theming, including dark mode

That is a lot of ground to cover. Let us start with the basics.

Getting It Installed

The package name has not changed, so installation is the same as before:

npm install react-split-pane
# or
yarn add react-split-pane

You will need React 17 or later and Node.js 20 or later. IE11 support has been dropped.

Your First v3 Split

A Simple Side-by-Side

The API has changed significantly from v0.1.x. Children are now wrapped in explicit Pane components, and size constraints live on each Pane rather than on the parent:

import { SplitPane, Pane } from "react-split-pane";
import "react-split-pane/styles.css";

const App = () => {
  return (
    <SplitPane direction="horizontal">
      <Pane minSize={200} defaultSize={300}>
        <nav>Sidebar</nav>
      </Pane>
      <Pane>
        <main>Main Content</main>
      </Pane>
    </SplitPane>
  );
};

Note the optional stylesheet import. Version 3 ships a default CSS file with sensible divider styling and dark mode support via prefers-color-scheme. You can skip it and style everything yourself if you prefer.

More Than Two Panes

One of the most requested features was multi-pane support. In v0.1.x, you had to nest SplitPane components to get more than two panels. Now you just add more Pane children:

import { SplitPane, Pane } from "react-split-pane";
import "react-split-pane/styles.css";

const ThreeColumnLayout = () => {
  return (
    <SplitPane direction="horizontal">
      <Pane minSize={150} defaultSize={200}>
        <aside>File Tree</aside>
      </Pane>
      <Pane minSize={300}>
        <section>Editor</section>
      </Pane>
      <Pane minSize={200} defaultSize={250}>
        <aside>Preview</aside>
      </Pane>
    </SplitPane>
  );
};

Each divider between panes is independently draggable. Three panes, two dividers, no nesting required.

Listening to Resize Events

The callback API is cleaner in v3. The onResize handler receives an array of all pane sizes, and as of v3.2.0, onResizeStart and onResizeEnd include the pointerType so you can distinguish between mouse, touch, and pen input:

import { SplitPane, Pane } from "react-split-pane";

const ResizeAwareLayout = () => {
  return (
    <SplitPane
      direction="horizontal"
      onResize={(sizes) => {
        console.log("Current sizes:", sizes);
      }}
      onResizeEnd={({ pointerType }) => {
        console.log(`Resize finished via ${pointerType}`);
      }}
    >
      <Pane defaultSize="40%">
        <div>Left</div>
      </Pane>
      <Pane>
        <div>Right</div>
      </Pane>
    </SplitPane>
  );
};

Power Features

Snap Points for Precise Layouts

Snap points let you define positions where the divider "sticks" as the user drags. This is great for layouts where you want a collapsed sidebar state and a fully open state with nothing awkward in between:

import { SplitPane, Pane } from "react-split-pane";

const SnappingSidebar = () => {
  return (
    <SplitPane
      direction="horizontal"
      snapPoints={[60, 250]}
      snapTolerance={20}
    >
      <Pane minSize={60} defaultSize={250}>
        <nav>Sidebar</nav>
      </Pane>
      <Pane>
        <main>Content</main>
      </Pane>
    </SplitPane>
  );
};

Drag the divider near 60px and it snaps to a collapsed icon-only sidebar. Drag it near 250px and it snaps to the fully expanded state. The snapTolerance controls how close you need to get before the snap kicks in.

Remembering Layouts with usePersistence

In the old version, persisting pane sizes meant wiring up localStorage yourself. Version 3 ships a dedicated hook:

import { SplitPane, Pane } from "react-split-pane";
import { usePersistence } from "react-split-pane/persistence";

const PersistentLayout = () => {
  const { sizes, onResize } = usePersistence({
    key: "editor-layout",
    storage: localStorage,
    debounce: 300,
  });

  return (
    <SplitPane direction="horizontal" onResize={onResize}>
      <Pane defaultSize={sizes?.[0] ?? 300}>
        <nav>Sidebar</nav>
      </Pane>
      <Pane>
        <main>Editor</main>
      </Pane>
    </SplitPane>
  );
};

The hook handles serialization, debounced writes, and restoring sizes on mount. Switch localStorage to sessionStorage if you only want the layout remembered for the current tab.

Custom Dividers and CSS Theming

The divider prop accepts a custom React component, giving you full control over the drag handle appearance. And even without a custom component, the CSS custom properties make quick styling easy:

import { SplitPane, Pane } from "react-split-pane";
import "react-split-pane/styles.css";

const ThemedSplit = () => {
  return (
    <SplitPane
      direction="horizontal"
      style={{
        "--split-pane-divider-size": "6px",
        "--split-pane-divider-color": "#e2e8f0",
        "--split-pane-divider-color-hover": "#3b82f6",
        "--split-pane-focus-color": "#3b82f6",
      } as React.CSSProperties}
    >
      <Pane defaultSize="50%">
        <div>Left</div>
      </Pane>
      <Pane>
        <div>Right</div>
      </Pane>
    </SplitPane>
  );
};

Keyboard Navigation

Accessibility was a first-class concern in v3. Every divider is keyboard-accessible out of the box:

  • Arrow keys resize by 10px per press
  • Shift + Arrow resizes by 50px for faster adjustment
  • Home / End collapse or expand to the minimum or maximum size
  • Tab moves focus between dividers

No extra props needed. It just works.

Migrating from v0.1.x

The API changes are significant but mechanical. Here is a quick reference:

v0.1.x v3
split="vertical" direction="horizontal"
split="horizontal" direction="vertical"
Bare children Wrap in <Pane>
minSize on SplitPane minSize on individual <Pane>
defaultSize on SplitPane defaultSize on individual <Pane>
onDragFinished onResizeEnd
resizerStyle prop CSS custom properties or divider prop

The naming swap between split and direction is the most confusing part. In v0.1.x, split="vertical" meant the divider was vertical (panes side by side). In v3, direction="horizontal" means the panes are arranged horizontally, which is the same visual result. Same layout, different naming convention.

One gotcha to watch for: SplitPane uses width: 100% and height: 100%, so its parent container must have explicit dimensions. For vertical direction splits, make sure the parent has an explicit height like height: 100vh. This was true in v0.1.x too, but it trips up a lot of newcomers.

Wrapping Up

React Split Pane v3 is a serious upgrade. The library went from a battle-tested but aging class component to a modern, accessible, TypeScript-native toolkit that supports multi-pane layouts, snap points, built-in persistence, and clean CSS theming. The migration from v0.1.x requires updating your component tree, but the new API is more explicit and more capable.

If you are already using react-split-pane in a project, v3 is worth the upgrade for the accessibility improvements and React 19 support alone. If you are starting fresh and evaluating options, react-split-pane now competes on features while keeping a simpler, more opinionated API than headless alternatives. At under 5KB with zero dependencies, it earns its place in the toolkit.