flutter_web_split_view
A production-ready Flutter package for resizable split-pane layouts, optimized for Flutter Web and desktop-style applications.
Build professional layouts like:
- ๐ฅ๏ธ IDE-style code editors (VS Code, IntelliJ style)
- ๐ Admin dashboards with resizable panels
- ๐ File explorers with sidebar + content
- ๐ CMS tools with preview panes
- ๐ Analytics panels with filter + chart sections
- ๐ฌ Chat applications (sidebar list + conversation)
- ๐จ Nested split workspaces for complex layouts
๐ฅ Demo

Try it live! Run the example app to see all features in action:
cd example && flutter run -d chrome
โจ Features
| Feature | Description |
|---|---|
| ๐ Horizontal & Vertical | Split views in any direction |
| ๐ฑ๏ธ Draggable Divider | Smooth, responsive resizing |
| ๐ Min/Max Constraints | Control pane size limits |
| ๐ Ratio or Pixel Sizing | Flexible initial configuration |
| ๐ฎ Controller Support | Programmatic control via SplitViewController |
| ๐ Collapsible Panes | Toggle sidebar/panel visibility |
| ๐จ Custom Dividers | Build your own divider UI |
| ๐ Browser Resize Aware | Handles window/container resizes |
| ๐ Fixed Pane Mode | Lock a pane during resizes |
| ๐ช Nested Split Views | Build complex dashboard layouts |
| ๐ Web & Desktop Optimized | Perfect for mouse-driven interfaces |
| ๐ฑ Mobile Support | Works on all platforms |
๐ฆ Installation
Add this to your pubspec.yaml:
dependencies:
flutter_web_split_view: ^1.0.0
Then run:
flutter pub get
๐ Quick Start
Basic horizontal split (sidebar + content)
import 'package:flutter/material.dart';
import 'package:flutter_web_split_view/flutter_web_split_view.dart';
class MyPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SplitView(
direction: Axis.horizontal,
initialRatio: 0.25,
minFirstPaneSize: 200,
minSecondPaneSize: 400,
dividerThickness: 8,
first: const SidebarWidget(),
second: const ContentWidget(),
);
}
}
๐ Complete Examples
1๏ธโฃ Basic Horizontal Split
SplitView(
first: const SidebarWidget(),
second: const ContentWidget(),
)
2๏ธโฃ Vertical Split (Top/Bottom)
SplitView(
direction: Axis.vertical,
initialRatio: 0.6,
minFirstPaneSize: 150,
minSecondPaneSize: 100,
first: const EditorPanel(),
second: const TerminalPanel(),
)
3๏ธโฃ Using a Controller (Programmatic Control)
final controller = SplitViewController(initialRatio: 0.35);
// In your widget:
SplitView(
controller: controller,
first: const Sidebar(),
second: const Content(),
)
// Control from anywhere:
controller.setRatio(0.5); // Set ratio
controller.setFirstPaneSize(320); // Set pixel size
controller.collapseFirst(); // Collapse first pane
controller.expand(); // Expand collapsed panes
controller.toggleFirst(); // Toggle collapse
4๏ธโฃ Collapsible Sidebar
SplitView(
initialRatio: 0.25,
collapsibleFirst: true,
collapseThreshold: 100,
minFirstPaneSize: 80,
minSecondPaneSize: 320,
first: const Sidebar(),
second: const Content(),
)
5๏ธโฃ Custom Divider
// Simple color customization
SplitView(
dividerThickness: 12,
dividerColor: Colors.blue,
first: const Sidebar(),
second: const Content(),
)
// Fully custom divider
SplitView(
dividerBuilder: (context, direction, thickness, isCollapsed, onToggle) {
return GestureDetector(
onTap: onToggle,
child: Container(
color: isCollapsed ? Colors.red : Colors.blue,
child: Center(
child: Icon(
direction == Axis.horizontal
? (isCollapsed ? Icons.chevron_right : Icons.drag_indicator)
: (isCollapsed ? Icons.expand_more : Icons.drag_handle),
),
),
),
);
},
first: const Sidebar(),
second: const Content(),
)
6๏ธโฃ Dashboard Layout (Nested)
SplitView(
initialRatio: 0.22,
minFirstPaneSize: 220,
minSecondPaneSize: 500,
first: const NavigationPanel(),
second: SplitView(
direction: Axis.vertical,
initialRatio: 0.7,
minFirstPaneSize: 300,
minSecondPaneSize: 180,
first: const AnalyticsWorkspace(),
second: const ActivityPanel(),
),
)
7๏ธโฃ Persist Layout Preferences
SplitView(
onRatioChanged: (ratio) {
// Save to SharedPreferences, Hive, etc.
prefs.setDouble('split_ratio', ratio);
},
onSizeChanged: (first, second, total) {
print('First: $first, Second: $second, Total: $total');
},
first: const Sidebar(),
second: const Content(),
)
โ๏ธ API Reference
SplitView
| Parameter | Type | Default | Description |
|---|---|---|---|
first |
Widget |
required | First (left/top) pane widget |
second |
Widget |
required | Second (right/bottom) pane widget |
direction |
Axis |
Axis.horizontal |
Split direction |
initialRatio |
double |
0.5 |
Initial ratio of first pane (0.0โ1.0) |
initialFirstPaneSize |
double? |
0.0 |
Initial first pane size in pixels (takes precedence over ratio) |
minFirstPaneSize |
double |
0.0 |
Minimum first pane size |
maxFirstPaneSize |
double |
double.infinity |
Maximum first pane size |
minSecondPaneSize |
double |
0.0 |
Minimum second pane size |
maxSecondPaneSize |
double |
double.infinity |
Maximum second pane size |
dividerThickness |
double |
8.0 |
Divider thickness in pixels |
dividerColor |
Color? |
null |
Divider color (default: theme divider color) |
dividerBuilder |
SplitViewDividerBuilder? |
null |
Custom divider widget builder |
onRatioChanged |
ValueChanged<double>? |
null |
Called when ratio changes |
onSizeChanged |
void Function(double, double, double)? |
null |
Called when pane sizes change |
controller |
SplitViewController? |
null |
External controller |
fixedPane |
SplitViewFixedPane |
SplitViewFixedPane.none |
Which pane stays fixed during resize |
collapsibleFirst |
bool |
false |
Allow first pane to collapse |
collapsibleSecond |
bool |
false |
Allow second pane to collapse |
collapseThreshold |
double |
48.0 |
Pixel threshold for collapse |
SplitViewController
Properties
| Property | Type | Description |
|---|---|---|
ratio |
double |
Current ratio of first pane (0.0โ1.0) |
firstPaneSize |
double |
Current first pane size in pixels |
isFirstCollapsed |
bool |
Whether first pane is collapsed |
isSecondCollapsed |
bool |
Whether second pane is collapsed |
isCollapsed |
bool |
Whether any pane is collapsed |
Methods
| Method | Description |
|---|---|
setRatio(double ratio) |
Set the pane ratio (0.0โ1.0) |
setFirstPaneSize(double size) |
Set first pane size in pixels |
collapseFirst() |
Collapse the first pane |
collapseSecond() |
Collapse the second pane |
expand() |
Expand all collapsed panes |
toggleFirst() |
Toggle first pane collapse |
toggleSecond() |
Toggle second pane collapse |
SplitViewFixedPane
| Value | Description |
|---|---|
none |
Both panes resize proportionally (default) |
first |
First pane stays fixed during resize |
second |
Second pane stays fixed during resize |
๐ก Best Practices
1. Set Minimum Sizes
Always provide sensible minimum sizes so panes remain usable:
SplitView(
minFirstPaneSize: 220, // Sidebar min width
minSecondPaneSize: 320, // Content min width
first: const Sidebar(),
second: const Content(),
)
2. Use Controllers for Dashboards
Controllers are perfect for:
- Restoring saved layout preferences
- Programmatic collapse/expand
- Dashboard workspace layouts
- IDE-like interfaces
3. Persist User Preferences
Save layout state for returning users:
SplitView(
onRatioChanged: (ratio) {
// Save to SharedPreferences
prefs.setDouble('layout_ratio', ratio);
},
// ...
)
4. Nest Carefully
Nested splits work great for complex layouts. Keep constraints realistic to avoid cramped UIs.
๐งช Testing
Run the test suite:
flutter test
Run static analysis:
flutter analyze
๐ฑ Platform Support
| Platform | Support Level | Notes |
|---|---|---|
| Web | โ Primary | Optimized for Flutter Web |
| macOS | โ Full | Perfect for desktop apps |
| Windows | โ Full | Perfect for desktop apps |
| Linux | โ Full | Perfect for desktop apps |
| iOS | โ Supported | Works but touch interactions differ |
| Android | โ Supported | Works but touch interactions differ |
โ ๏ธ Notes & Limitations
- Optimized for Web & Desktop: Primary design target is mouse/trackpad interfaces
- Mobile is supported: Touch works, but drag precision is limited
- Deep nesting: Very deep nesting may increase layout complexity
๐ค Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
Quick contribution steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Add tests for new functionality
- Run
flutter analyze && flutter test - Commit your changes
- Open a Pull Request
๐ License
MIT License โ see LICENSE for details.
๐ฆ Changelog
See CHANGELOG.md for release history.
๐ฌ Community & Support
- GitHub Issues: Report bugs or request features
- GitHub Discussions: Ask questions
Made with โค๏ธ for the Flutter community
If this package helped you, please consider giving it a like on pub.dev โญ
Libraries
- flutter_web_split_view
- A production-grade split-pane / resizable layout widget for Flutter Web and desktop.