Split
Split divides a container into multiple resizable areas and supports horizontal, vertical, collapsible, and lazy update layouts.
Basic Usage
When size is not specified, the remaining space is automatically distributed across unspecified panels.
<template>
<b-split class="split-demo">
<b-split-panel size="30%">
<div class="split-panel is-soft">Navigation</div>
</b-split-panel>
<b-split-panel :min="220">
<div class="split-panel is-warm">Content</div>
</b-split-panel>
</b-split>
</template>
<style scoped>
.split-demo {
height: 280px;
border: 1px solid #e8edf4;
border-radius: 14px;
background: #fff;
}
.split-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-size: 15px;
font-weight: 600;
color: #31415c;
}
.split-panel.is-soft {
background: linear-gradient(135deg, #f7fbff 0%, #eef5ff 100%);
}
.split-panel.is-warm {
background: linear-gradient(135deg, #fffaf2 0%, #fff3df 100%);
}
</style>Vertical Layout
Use layout="vertical" to switch to a top-bottom layout.
<template>
<b-split class="split-demo" layout="vertical">
<b-split-panel size="38%">
<div class="split-panel is-soft">Top Area</div>
</b-split-panel>
<b-split-panel :min="120">
<div class="split-panel is-cool">Bottom Area</div>
</b-split-panel>
</b-split>
</template>
<style scoped>
.split-demo {
height: 280px;
border: 1px solid #e8edf4;
border-radius: 14px;
background: #fff;
}
.split-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-size: 15px;
font-weight: 600;
color: #31415c;
}
.split-panel.is-soft {
background: linear-gradient(180deg, #f7fbff 0%, #eef5ff 100%);
}
.split-panel.is-cool {
background: linear-gradient(180deg, #f3fbf8 0%, #e7f7f1 100%);
}
</style>Collapsible Panels
Set collapsible on a panel to quickly collapse or restore it from the split bar buttons.
<template>
<b-split class="split-demo">
<b-split-panel size="180" collapsible min="80">
<div class="split-panel is-soft">Outline</div>
</b-split-panel>
<b-split-panel collapsible>
<div class="split-panel is-cool">Editor</div>
</b-split-panel>
<b-split-panel size="24%">
<div class="split-panel is-warm">Preview</div>
</b-split-panel>
</b-split>
</template>
<style scoped>
.split-demo {
height: 280px;
border: 1px solid #e8edf4;
border-radius: 14px;
background: #fff;
}
.split-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-size: 15px;
font-weight: 600;
color: #31415c;
}
.split-panel.is-soft {
background: linear-gradient(135deg, #f7fbff 0%, #eef5ff 100%);
}
.split-panel.is-cool {
background: linear-gradient(135deg, #f3fbf8 0%, #e7f7f1 100%);
}
.split-panel.is-warm {
background: linear-gradient(135deg, #fffaf2 0%, #fff3df 100%);
}
</style>Panel Size
size accepts numbers, px, or percentages. You can also read the current size with v-model:size.
<template>
<b-split class="split-demo" @resize-end="handleResizeEnd">
<b-split-panel>
<div class="split-panel is-soft">Assets</div>
</b-split-panel>
<b-split-panel v-model:size="size" :min="120" :max="240">
<div class="split-panel is-cool">{{ size }}px</div>
</b-split-panel>
<b-split-panel>
<div class="split-panel is-warm">Workspace</div>
</b-split-panel>
</b-split>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const size = ref(160)
const handleResizeEnd = (_index: number, sizes: number[]) => {
size.value = Math.round(sizes[1] || 0)
}
</script>
<style scoped>
.split-demo {
height: 280px;
border: 1px solid #e8edf4;
border-radius: 14px;
background: #fff;
}
.split-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-size: 15px;
font-weight: 600;
color: #31415c;
}
.split-panel.is-soft {
background: linear-gradient(135deg, #f7fbff 0%, #eef5ff 100%);
}
.split-panel.is-cool {
background: linear-gradient(135deg, #f3fbf8 0%, #e7f7f1 100%);
}
.split-panel.is-warm {
background: linear-gradient(135deg, #fffaf2 0%, #fff3df 100%);
}
</style>Lazy Update
When lazy is enabled, only the drag bar moves during dragging. Panel sizes are committed after the drag ends.
The middle panel size updates after dragging ends.
<template>
<div>
<p class="split-tip">The middle panel size updates after dragging ends.</p>
<b-split class="split-demo" lazy>
<b-split-panel size="25%" collapsible>
<div class="split-panel is-soft">Sidebar</div>
</b-split-panel>
<b-split-panel v-model:size="size" :min="120">
<div class="split-panel is-cool">Current width: {{ size }}px</div>
</b-split-panel>
<b-split-panel collapsible>
<div class="split-panel is-warm">Details</div>
</b-split-panel>
</b-split>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const size = ref(180)
</script>
<style scoped>
.split-tip {
margin-bottom: 10px;
color: #5b6b88;
}
.split-demo {
height: 280px;
border: 1px solid #e8edf4;
border-radius: 14px;
background: #fff;
}
.split-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-size: 15px;
font-weight: 600;
color: #31415c;
}
.split-panel.is-soft {
background: linear-gradient(135deg, #f7fbff 0%, #eef5ff 100%);
}
.split-panel.is-cool {
background: linear-gradient(135deg, #f3fbf8 0%, #e7f7f1 100%);
}
.split-panel.is-warm {
background: linear-gradient(135deg, #fffaf2 0%, #fff3df 100%);
}
</style>Disable Dragging
If either adjacent panel sets resizable="false", the related split bar becomes non-draggable.
<template>
<b-split class="split-demo">
<b-split-panel size="28%">
<div class="split-panel is-soft">Resizable</div>
</b-split-panel>
<b-split-panel :resizable="false" size="180">
<div class="split-panel is-cool">Fixed Width</div>
</b-split-panel>
<b-split-panel>
<div class="split-panel is-warm">Content</div>
</b-split-panel>
</b-split>
</template>
<style scoped>
.split-demo {
height: 280px;
border: 1px solid #e8edf4;
border-radius: 14px;
background: #fff;
}
.split-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-size: 15px;
font-weight: 600;
color: #31415c;
}
.split-panel.is-soft {
background: linear-gradient(135deg, #f7fbff 0%, #eef5ff 100%);
}
.split-panel.is-cool {
background: linear-gradient(135deg, #f3fbf8 0%, #e7f7f1 100%);
}
.split-panel.is-warm {
background: linear-gradient(135deg, #fffaf2 0%, #fff3df 100%);
}
</style>Multiple Panels
Split supports layouts with more than two panels.
<template>
<b-split class="split-demo">
<b-split-panel size="18%">
<div class="split-panel is-soft">A</div>
</b-split-panel>
<b-split-panel size="22%" collapsible>
<div class="split-panel is-cool">B</div>
</b-split-panel>
<b-split-panel :min="140">
<div class="split-panel is-warm">C</div>
</b-split-panel>
<b-split-panel size="20%">
<div class="split-panel is-deep">D</div>
</b-split-panel>
</b-split>
</template>
<style scoped>
.split-demo {
height: 280px;
border: 1px solid #e8edf4;
border-radius: 14px;
background: #fff;
}
.split-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-size: 15px;
font-weight: 600;
color: #31415c;
}
.split-panel.is-soft {
background: linear-gradient(135deg, #f7fbff 0%, #eef5ff 100%);
}
.split-panel.is-cool {
background: linear-gradient(135deg, #f3fbf8 0%, #e7f7f1 100%);
}
.split-panel.is-warm {
background: linear-gradient(135deg, #fffaf2 0%, #fff3df 100%);
}
.split-panel.is-deep {
background: linear-gradient(135deg, #f6f3ff 0%, #ece7ff 100%);
}
</style>Split Props
| Parameter | Description | Type | Options | Default |
|---|---|---|---|---|
| layout | Panel layout direction | String | 'horizontal' | 'vertical' | horizontal |
| lazy | Whether to enable lazy updates | Boolean | — | false |
Split Events
| Event | Description | Return Value |
|---|---|---|
| resize-start | Triggered when dragging starts | (index: number, sizes: number[]) |
| resize | Triggered while dragging | (index: number, sizes: number[]) |
| resize-end | Triggered when dragging ends | (index: number, sizes: number[]) |
| collapse | Triggered when a collapse button is clicked | (index: number, type: 'start' | 'end', sizes: number[]) |
SplitPanel Props
| Parameter | Description | Type | Default |
|---|---|---|---|
| size | Panel size, supports numbers, px, or percentages | String / Number | — |
| min | Minimum panel size, supports numbers, px, or percentages | String / Number | — |
| max | Maximum panel size, supports numbers, px, or percentages | String / Number | — |
| resizable | Whether the panel can be resized | Boolean | true |
| collapsible | Whether collapse controls are enabled. Supports boolean or directional object | Boolean / { start?: boolean; end?: boolean } | false |
SplitPanel Events
| Event | Description | Return Value |
|---|---|---|
| update:size | Triggered when panel size changes | (size: string | number) |
SplitPanel Slots
| Name | Description |
|---|---|
| default | Default panel content |
| start-collapsible | Custom start-side collapse trigger |
| end-collapsible | Custom end-side collapse trigger |