Skip to content

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.

Navigation
Content
<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.

Top Area
Bottom Area
<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.

Outline
Editor
Preview
<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.

Assets
160px
Workspace
<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.

Sidebar
Current width: 180px
Details
<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.

Resizable
Fixed Width
Content
<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.

A
B
C
D
<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

ParameterDescriptionTypeOptionsDefault
layoutPanel layout directionString'horizontal' | 'vertical'horizontal
lazyWhether to enable lazy updatesBooleanfalse

Split Events

EventDescriptionReturn Value
resize-startTriggered when dragging starts(index: number, sizes: number[])
resizeTriggered while dragging(index: number, sizes: number[])
resize-endTriggered when dragging ends(index: number, sizes: number[])
collapseTriggered when a collapse button is clicked(index: number, type: 'start' | 'end', sizes: number[])

SplitPanel Props

ParameterDescriptionTypeDefault
sizePanel size, supports numbers, px, or percentagesString / Number
minMinimum panel size, supports numbers, px, or percentagesString / Number
maxMaximum panel size, supports numbers, px, or percentagesString / Number
resizableWhether the panel can be resizedBooleantrue
collapsibleWhether collapse controls are enabled. Supports boolean or directional objectBoolean / { start?: boolean; end?: boolean }false

SplitPanel Events

EventDescriptionReturn Value
update:sizeTriggered when panel size changes(size: string | number)

SplitPanel Slots

NameDescription
defaultDefault panel content
start-collapsibleCustom start-side collapse trigger
end-collapsibleCustom end-side collapse trigger