
Product
Introducing Reports: An Extensible Reporting Framework for Socket Data
Explore exportable charts for vulnerabilities, dependencies, and usage with Reports, Socket’s new extensible reporting framework.
react-split-pane
Advanced tools
Modern, accessible, TypeScript-first split pane component for React.
npm install react-split-pane
# or
yarn add react-split-pane
# or
pnpm add react-split-pane
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%andheight: 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.
<SplitPane direction="horizontal">
<Pane defaultSize="25%">
<LeftPanel />
</Pane>
<Pane>
<RightPanel />
</Pane>
</SplitPane>
<SplitPane direction="vertical">
<Pane defaultSize="100px">
<Header />
</Pane>
<Pane>
<Content />
</Pane>
</SplitPane>
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>
);
}
<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>
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>
);
}
| Option | Type | Default | Description |
|---|---|---|---|
key | string | Required | Storage key for persisting sizes |
storage | Storage | localStorage | Storage backend (localStorage or sessionStorage) |
debounce | number | 300 | Debounce delay in ms before saving |
// Use sessionStorage instead of localStorage
const [sizes, setSizes] = usePersistence({
key: 'my-layout',
storage: sessionStorage,
debounce: 500,
});
<SplitPane
snapPoints={[200, 400, 600]}
snapTolerance={20}
>
{/* panes */}
</SplitPane>
function CustomDivider(props) {
return (
<div {...props} style={{ ...props.style, background: 'blue' }}>
<GripIcon />
</div>
);
}
<SplitPane divider={CustomDivider}>
{/* panes */}
</SplitPane>
The divider is fully keyboard accessible:
step pixels (default: 10px)| Prop | Type | Default | Description |
|---|---|---|---|
direction | 'horizontal' | 'vertical' | 'horizontal' | Layout direction |
resizable | boolean | true | Whether panes can be resized |
snapPoints | number[] | [] | Snap points in pixels |
snapTolerance | number | 10 | Snap tolerance in pixels |
step | number | 10 | Keyboard resize step |
onResizeStart | (event) => void | - | Called when resize starts |
onResize | (sizes, event) => void | - | Called during resize |
onResizeEnd | (sizes, event) => void | - | Called when resize ends |
className | string | - | CSS class name |
style | CSSProperties | - | Inline styles |
divider | ComponentType | - | Custom divider component |
dividerClassName | string | - | Divider class name |
dividerStyle | CSSProperties | - | Divider inline styles |
| Prop | Type | Default | Description |
|---|---|---|---|
defaultSize | string | number | '50%' | Initial size (uncontrolled) |
size | string | number | - | Controlled size |
minSize | string | number | 0 | Minimum size |
maxSize | string | number | Infinity | Maximum size |
className | string | - | CSS class name |
style | CSSProperties | - | Inline styles |
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.
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>
);
}
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; }
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.
.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;
}
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);
}
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);
}
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.
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>
Note: IE11 is not supported. Use v0.1.x for IE11 compatibility.
Contributions are welcome! Please see CONTRIBUTING.md.
MIT © tomkp
The react-resizable package provides a set of React components for creating resizable elements. It is more focused on individual resizable components rather than split panes, making it more flexible for custom resizable layouts.
The react-grid-layout package offers a grid-based layout system with draggable and resizable widgets. It is more feature-rich compared to react-split-pane, providing a more comprehensive solution for complex grid layouts.
The react-split package is a lightweight alternative for creating split views in React applications. It offers similar functionality to react-split-pane but with a smaller footprint and fewer dependencies.
FAQs
React split-pane component with hooks and TypeScript
The npm package react-split-pane receives a total of 229,239 weekly downloads. As such, react-split-pane popularity was classified as popular.
We found that react-split-pane demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?

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.

Product
Explore exportable charts for vulnerabilities, dependencies, and usage with Reports, Socket’s new extensible reporting framework.

Product
Socket for Jira lets teams turn alerts into Jira tickets with manual creation, automated ticketing rules, and two-way sync.

Company News
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.