Launch Week Day 1: Socket for Jira Is Now Available.Learn More
Socket
Book a DemoSign in
Socket

react-split-pane

Package Overview
Dependencies
Maintainers
2
Versions
97
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-split-pane

React split-pane component with hooks and TypeScript

latest
Source
npmnpm
Version
3.2.0
Version published
Weekly downloads
277K
-9.4%
Maintainers
2
Weekly downloads
 
Created
Source

React Split Pane v3

Modern, accessible, TypeScript-first split pane component for React.

NPM version NPM license NPM downloads Bundle size

Live Examples

✨ Features

  • 🪝 Hooks-based - Built with modern React patterns
  • 📘 TypeScript - Full type safety out of the box
  • Accessible - Keyboard navigation, ARIA attributes, screen reader support
  • 📱 Touch-friendly - Full mobile/tablet support
  • 🎯 Flexible - Controlled/uncontrolled modes, nested layouts, 2+ panes
  • 🪶 Lightweight - < 5KB gzipped
  • Performant - RAF-throttled resize, optimized renders
  • 🎨 Customizable - Full styling control

Installation

npm install react-split-pane

# or
yarn add react-split-pane

# or
pnpm add react-split-pane

Quick Start

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

function App() {
  return (
    <SplitPane direction="horizontal">
      <Pane minSize="200px" defaultSize="300px">
        <Sidebar />
      </Pane>
      <Pane>
        <MainContent />
      </Pane>
    </SplitPane>
  );
}

Note: SplitPane requires its container to have explicit dimensions. The component uses width: 100% and height: 100%, so the parent element must have a defined size. For vertical splits, ensure the parent has an explicit height (e.g., height: 100vh). See Container Sizing for details.

Basic Usage

Horizontal Split (Side-by-Side)

<SplitPane direction="horizontal">
  <Pane defaultSize="25%">
    <LeftPanel />
  </Pane>
  <Pane>
    <RightPanel />
  </Pane>
</SplitPane>

Vertical Split (Top-Bottom)

<SplitPane direction="vertical">
  <Pane defaultSize="100px">
    <Header />
  </Pane>
  <Pane>
    <Content />
  </Pane>
</SplitPane>

Controlled Mode

function App() {
  const [sizes, setSizes] = useState([300, 500]);

  return (
    <SplitPane onResize={setSizes}>
      <Pane size={sizes[0]} minSize="200px">
        <Sidebar />
      </Pane>
      <Pane size={sizes[1]}>
        <Main />
      </Pane>
    </SplitPane>
  );
}

Nested Layouts

<SplitPane direction="vertical">
  <Pane defaultSize="60px">
    <Header />
  </Pane>

  <SplitPane direction="horizontal">
    <Pane defaultSize="250px" minSize="150px">
      <Sidebar />
    </Pane>

    <SplitPane direction="vertical">
      <Pane>
        <Editor />
      </Pane>
      <Pane defaultSize="200px">
        <Console />
      </Pane>
    </SplitPane>
  </SplitPane>
</SplitPane>

Advanced Features

Persistence

The usePersistence hook saves and restores pane sizes to localStorage (or sessionStorage):

import { usePersistence } from 'react-split-pane/persistence';

function App() {
  const [sizes, setSizes] = usePersistence({ key: 'my-layout' });

  return (
    <SplitPane onResize={setSizes}>
      <Pane size={sizes[0] || 300}>
        <Sidebar />
      </Pane>
      <Pane size={sizes[1]}>
        <Main />
      </Pane>
    </SplitPane>
  );
}

usePersistence Options

OptionTypeDefaultDescription
keystringRequiredStorage key for persisting sizes
storageStoragelocalStorageStorage backend (localStorage or sessionStorage)
debouncenumber300Debounce delay in ms before saving
// Use sessionStorage instead of localStorage
const [sizes, setSizes] = usePersistence({
  key: 'my-layout',
  storage: sessionStorage,
  debounce: 500,
});

Snap Points

<SplitPane
  snapPoints={[200, 400, 600]}
  snapTolerance={20}
>
  {/* panes */}
</SplitPane>

Custom Divider

function CustomDivider(props) {
  return (
    <div {...props} style={{ ...props.style, background: 'blue' }}>
      <GripIcon />
    </div>
  );
}

<SplitPane divider={CustomDivider}>
  {/* panes */}
</SplitPane>

Keyboard Navigation

The divider is fully keyboard accessible:

  • Arrow Keys: Resize by step pixels (default: 10px)
  • Shift + Arrow: Resize by larger step (default: 50px)
  • Home: Minimize left/top pane
  • End: Maximize left/top pane
  • Escape: Restore pane sizes to initial state
  • Tab: Navigate between dividers

API Reference

SplitPane Props

PropTypeDefaultDescription
direction'horizontal' | 'vertical''horizontal'Layout direction
resizablebooleantrueWhether panes can be resized
snapPointsnumber[][]Snap points in pixels
snapTolerancenumber10Snap tolerance in pixels
stepnumber10Keyboard resize step
onResizeStart(event) => void-Called when resize starts
onResize(sizes, event) => void-Called during resize
onResizeEnd(sizes, event) => void-Called when resize ends
classNamestring-CSS class name
styleCSSProperties-Inline styles
dividerComponentType-Custom divider component
dividerClassNamestring-Divider class name
dividerStyleCSSProperties-Divider inline styles

Pane Props

PropTypeDefaultDescription
defaultSizestring | number'50%'Initial size (uncontrolled)
sizestring | number-Controlled size
minSizestring | number0Minimum size
maxSizestring | numberInfinityMaximum size
classNamestring-CSS class name
styleCSSProperties-Inline styles

Container Sizing

SplitPane uses width: 100% and height: 100% and measures its container via ResizeObserver. The parent container must have explicit dimensions for panes to render correctly.

Common Issue: Invisible Panes

If your pane content doesn't appear, the most common cause is a missing height on the parent container. This is especially true for vertical splits:

// ❌ Won't work - parent has no height
function App() {
  return (
    <div>
      <SplitPane direction="vertical">
        <Pane><div>Top</div></Pane>
        <Pane><div>Bottom</div></Pane>
      </SplitPane>
    </div>
  );
}

// ✅ Works - parent has explicit height
function App() {
  return (
    <div style={{ height: '100vh' }}>
      <SplitPane direction="vertical">
        <Pane><div>Top</div></Pane>
        <Pane><div>Bottom</div></Pane>
      </SplitPane>
    </div>
  );
}

Solutions

  • Set explicit height on parent (recommended for most cases):

    .container { height: 100vh; }
    
  • Use absolute positioning:

    .container { position: absolute; inset: 0; }
    
  • Use flexbox with flex-grow:

    .parent { display: flex; flex-direction: column; height: 100vh; }
    .container { flex: 1; }
    

Styling

Default Stylesheet

Import the optional default styles with CSS custom properties:

import 'react-split-pane/styles.css';

Customize via CSS variables:

.my-split-pane {
  --split-pane-divider-size: 8px;
  --split-pane-divider-color: #e0e0e0;
  --split-pane-divider-color-hover: #b0b0b0;
  --split-pane-focus-color: #2196f3;
}

The default styles include dark mode support via prefers-color-scheme.

Basic Styles

.split-pane {
  height: 100vh;
}

.split-pane-divider {
  background: #e0e0e0;
  transition: background 0.2s;
}

.split-pane-divider:hover {
  background: #b0b0b0;
}

.split-pane-divider:focus {
  outline: 2px solid #2196f3;
  outline-offset: -2px;
}

Expanded Hover Area

This classic pattern creates a thin visible divider with a larger grabbable area that reveals on hover:

.split-pane-divider {
  background: #000;
  opacity: 0.2;
  z-index: 1;
  box-sizing: border-box;
  background-clip: padding-box;
}

.split-pane-divider:hover {
  transition: all 0.2s ease;
}

.split-pane-divider.horizontal {
  width: 11px;
  margin: 0 -5px;
  border-left: 5px solid rgba(255, 255, 255, 0);
  border-right: 5px solid rgba(255, 255, 255, 0);
  cursor: col-resize;
}

.split-pane-divider.horizontal:hover {
  border-left: 5px solid rgba(0, 0, 0, 0.5);
  border-right: 5px solid rgba(0, 0, 0, 0.5);
}

.split-pane-divider.vertical {
  height: 11px;
  margin: -5px 0;
  border-top: 5px solid rgba(255, 255, 255, 0);
  border-bottom: 5px solid rgba(255, 255, 255, 0);
  cursor: row-resize;
}

.split-pane-divider.vertical:hover {
  border-top: 5px solid rgba(0, 0, 0, 0.5);
  border-bottom: 5px solid rgba(0, 0, 0, 0.5);
}

Minimal Divider

A subtle single-pixel divider:

.split-pane-divider.horizontal {
  width: 1px;
  margin: 0;
  background: linear-gradient(to right, transparent, #ccc, transparent);
}

.split-pane-divider.vertical {
  height: 1px;
  margin: 0;
  background: linear-gradient(to bottom, transparent, #ccc, transparent);
}

Tailwind CSS & shadcn/ui

React Split Pane works seamlessly with Tailwind CSS and shadcn/ui. See TAILWIND.md for detailed integration examples including custom dividers and CSS variable overrides.

Migration from v0.1.x or v2.x

See MIGRATION.md for detailed migration guide.

Quick changes:

// v0.1.x
<SplitPane split="vertical" minSize={50} defaultSize={100}>
  <div>Pane 1</div>
  <div>Pane 2</div>
</SplitPane>

// v3
<SplitPane direction="horizontal">
  <Pane minSize="50px" defaultSize="100px">
    <div>Pane 1</div>
  </Pane>
  <Pane>
    <div>Pane 2</div>
  </Pane>
</SplitPane>

Browser Support

  • Chrome/Edge (latest 2 versions)
  • Firefox (latest 2 versions)
  • Safari (latest 2 versions)
  • Mobile browsers (iOS Safari, Chrome Android)

Note: IE11 is not supported. Use v0.1.x for IE11 compatibility.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md.

License

MIT © tomkp

Keywords

react

FAQs

Package last updated on 19 Feb 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts