Splitpanes

A Vue.js reliable, simple and touch-ready panes splitter / resizer.

Features

  • Light weight & no dependencies other than Vue JS
  • Only worry about your panes, the splitters are automatic
  • Nesting supported
  • Fully responsive
  • Support for touch devices
  • Push other panes or not
  • Double click a splitter to maximize pane
  • Programmatically set pane width or height
  • Programmatically add and remove panes
  • Also supports Vue 2 (legacy branch)

Github project  &  important notes

If you like Splitpanes, you canSupport the projectorSponsor the author!
Thank you so much to all the backers! 🙏
Do you need A UI framework? CheckoutWave UI
By the same awesome author.
1
I have a min width of 20%
2
3
4
5
<splitpanes style="height: 400px">
  <pane min-size="20">1</pane>
  <pane>
    <splitpanes horizontal>
      <pane>2</pane>
      <pane>3</pane>
      <pane>4</pane>
    </splitpanes>
  </pane>
  <pane>5</pane>
</splitpanes>
<splitpanes style="height: 400px"> <pane min-size="20">1</pane> <pane> <splitpanes horizontal> <pane>2</pane> <pane>3</pane> <pane>4</pane> </splitpanes> </pane> <pane>5</pane> </splitpanes>
.splitpanes__pane {
  display: flex;
  justify-content: center;
  align-items: center;
  font-family: Helvetica, Arial, sans-serif;
  color: rgba(255, 255, 255, 0.6);
  font-size: 5em;
}
.splitpanes__pane { display: flex; justify-content: center; align-items: center; font-family: Helvetica, Arial, sans-serif; color: rgba(255, 255, 255, 0.6); font-size: 5em; }

Installation

You have two options: NPM or <script> tag.

Via NPM

npm i splitpanes # For Vue 3
npm i splitpanes # For Vue 3
or
npm i splitpanes@legacy # For Vue 2
npm i splitpanes@legacy # For Vue 2

View and edit a workingVue 3 example, orVue 2 exampleon Codepen.

Then import the component and CSS:
import { Splitpanes, Pane } from 'splitpanes'
import 'splitpanes/dist/splitpanes.css'
import { Splitpanes, Pane } from 'splitpanes' import 'splitpanes/dist/splitpanes.css'

Via <script> tag

Include the Splitpanes script in your document <head> as follows:

<head>
  ...
  <script src="https://unpkg.com/vue"></script>
  <script src="https://unpkg.com/splitpanes"></script>
  <link href="https://unpkg.com/splitpanes/dist/splitpanes.css" rel="stylesheet">
</head>
<head> ... <script src="https://unpkg.com/vue"></script> <script src="https://unpkg.com/splitpanes"></script> <link href="https://unpkg.com/splitpanes/dist/splitpanes.css" rel="stylesheet"> </head>

How to use

Once included in your project, use as follows.

<splitpanes class="default-theme">
  <pane v-for="i in 3" :key="i">
    <div>{{ i }}</div>
  </pane>
</splitpanes>
<splitpanes class="default-theme"> <pane v-for="i in 3" :key="i"> <div>{{ i }}</div> </pane> </splitpanes>

No splitter tags!
The splitters will be added automatically between the <pane> tags.

By default the layout is vertical, if you need you can set the attribute horizontal on the <splitpanes> tag to change the layout to rows.

The CSS is external so you can easily override or choose not to include it at all.
If you want to use it, you can also optionally use the CSS class default-theme at the root of your splitpanes to apply the default theme like on this page.
If you want to go with your own style, you can check the Do Your Own Style example.

More examples

Horizontal layout, push other panes, min & max use

By default, you can also double click a splitter to maximize the next pane (displaying the first pane splitter is an option).

But if you want to disable this feature, you can set: :maximize-panes="false".

1
I have a min height of 20% & max height of 70%
2
3
I have a max height of 70%
<splitpanes class="default-theme" horizontal style="height: 400px">
  <pane min-size="20" max-size="70">
    <span>1</span>
  </pane>
  <pane>
    <span>2</span>
  </pane>
  <pane max-size="70">
    <span>3</span>
  </pane>
</splitpanes>
<splitpanes class="default-theme" horizontal style="height: 400px"> <pane min-size="20" max-size="70"> <span>1</span> </pane> <pane> <span>2</span> </pane> <pane max-size="70"> <span>3</span> </pane> </splitpanes>

Default pane width or height

Provide dimension of your panes when they first load (will be used for the width or height respectively for the vertical or horizontal layout).
If you provide a default width or height, make sure you provide it for all the panes and the total equals 100%.
If a pane is missing a default width or height, then all the panes will have the same width or height.
Note that setting a default value is different than setting a min or max value.

1
2
3
<splitpanes class="default-theme" horizontal style="height: 400px">
  <pane size="65">
    <span>1</span>
  </pane>
  <pane size="10">
    <span>2</span>
  </pane>
  <pane size="25">
    <span>3</span>
  </pane>
</splitpanes>
<splitpanes class="default-theme" horizontal style="height: 400px"> <pane size="65"> <span>1</span> </pane> <pane size="10"> <span>2</span> </pane> <pane size="25"> <span>3</span> </pane> </splitpanes>

Mix layout with nested splitpanes & prevent pushing other panes

Try it yourself on Codepen

1
2
3
4
5
<splitpanes class="default-theme" horizontal :push-other-panes="false" style="height: 400px">
  <pane>
    <span>1</span>
  </pane>
  <pane>
    <splitpanes :push-other-panes="false">
      <pane>
        <span>2</span>
      </pane>
      <pane>
        <span>3</span>
      </pane>
      <pane>
        <span>4</span>
      </pane>
    </splitpanes>
  </pane>
  <pane>
    <span>5</span>
  </pane>
</splitpanes>
<splitpanes class="default-theme" horizontal :push-other-panes="false" style="height: 400px"> <pane> <span>1</span> </pane> <pane> <splitpanes :push-other-panes="false"> <pane> <span>2</span> </pane> <pane> <span>3</span> </pane> <pane> <span>4</span> </pane> </splitpanes> </pane> <pane> <span>5</span> </pane> </splitpanes>

Lots of splitters & push other panes - all the panes have a min width of 5%

1
2
3
4
5
6
7
8
<splitpanes class="default-theme" style="height: 400px">
  <pane v-for="i in 8" :key="i" min-size="5">
    <span>{{ i }}</span>
  </pane>
</splitpanes>
<splitpanes class="default-theme" style="height: 400px"> <pane v-for="i in 8" :key="i" min-size="5"> <span>{{ i }}</span> </pane> </splitpanes>

Adding splitters on the fly

This example shows the reactivity when you add a new element dynamically in splitpanes.

1
2
3
<button @click="panesNumber++">Add pane</button>
<button @click="panesNumber--">Remove pane</button>

<splitpanes class="default-theme" style="height: 400px">
  <pane v-for="i in panesNumber" :key="i">
    <span>{{ i }}</span>
  </pane>
</splitpanes>
<button @click="panesNumber++">Add pane</button> <button @click="panesNumber--">Remove pane</button> <splitpanes class="default-theme" style="height: 400px"> <pane v-for="i in panesNumber" :key="i"> <span>{{ i }}</span> </pane> </splitpanes>
import { ref } from 'vue'
import { Splitpanes, Pane } from 'splitpanes'
import 'splitpanes/dist/splitpanes.css'

const panesNumber = ref(3)
import { ref } from 'vue' import { Splitpanes, Pane } from 'splitpanes' import 'splitpanes/dist/splitpanes.css' const panesNumber = ref(3)

Change direction & first splitter

When changing direction, all the panes current width or height will flip to adapt to the new layout.

Showing the first splitter is an option which allows user to double click the splitter to maximize the next pane.
The first splitter does not allow to resize the next pane.

1
2
3
<button @click="horizontal = !horizontal">Switch to {{ horizontal ? 'Vertical' : 'Horizontal' }}</button>
<button @click="firstSplitter = !firstSplitter">{{ firstSplitter ? 'Hide' : 'Show' }} First Splitter</button>

<splitpanes class="default-theme" :horizontal="horizontal" :first-splitter="firstSplitter" style="height: 400px">
  <pane v-for="i in 3" :key="i">
    <span>{{ i }}%</span>
  </pane>
</splitpanes>
<button @click="horizontal = !horizontal">Switch to {{ horizontal ? 'Vertical' : 'Horizontal' }}</button> <button @click="firstSplitter = !firstSplitter">{{ firstSplitter ? 'Hide' : 'Show' }} First Splitter</button> <splitpanes class="default-theme" :horizontal="horizontal" :first-splitter="firstSplitter" style="height: 400px"> <pane v-for="i in 3" :key="i"> <span>{{ i }}%</span> </pane> </splitpanes>
import { ref } from 'vue'
import { Splitpanes, Pane } from 'splitpanes'
import 'splitpanes/dist/splitpanes.css'

const horizontal = ref(false)
const firstSplitter = ref(false)
import { ref } from 'vue' import { Splitpanes, Pane } from 'splitpanes' import 'splitpanes/dist/splitpanes.css' const horizontal = ref(false) const firstSplitter = ref(false)

Programmatic resizing

This example shows the programmatic way of resizing panes and how it works both ways.

In this example, the default transition on the .splitpanes__pane element is removed so it looks fast and reactive.

50%
50%
<w-slider v-model="paneSize" label="First pane size" :min="0" :max="100">
<splitpanes
  class="default-theme"
  @resize="({ prevPane }) => paneSize = prevPane.size"
  style="height: 400px">
  <pane :size="paneSize">
    <span>{{ paneSize }}%</span>
  </pane>
  <pane :size="100 - paneSize">
    <span>{{ 100 - paneSize }}%</span>
  </pane>
</splitpanes>
<w-slider v-model="paneSize" label="First pane size" :min="0" :max="100"> <splitpanes class="default-theme" @resize="({ prevPane }) => paneSize = prevPane.size" style="height: 400px"> <pane :size="paneSize"> <span>{{ paneSize }}%</span> </pane> <pane :size="100 - paneSize"> <span>{{ 100 - paneSize }}%</span> </pane> </splitpanes>
import { ref } from 'vue'
import { Splitpanes, Pane } from 'splitpanes'
import 'splitpanes/dist/splitpanes.css'

const paneSize = ref(50)
import { ref } from 'vue' import { Splitpanes, Pane } from 'splitpanes' import 'splitpanes/dist/splitpanes.css' const paneSize = ref(50)

Persistent size after page reload

This example shows how to maintain and restore the size of the panes after a page reload.

30%
70%
<w-slider v-model="paneSize" label="First pane size" :min="0" :max="100">
<splitpanes
  class="default-theme"
  @resized="storePaneSize"
  style="height: 400px">
  <pane :size="paneSize">
    <span>{{ paneSize }}%</span>
  </pane>
  <pane :size="100 - paneSize">
    <span>{{ 100 - paneSize }}%</span>
  </pane>
</splitpanes>
<w-slider v-model="paneSize" label="First pane size" :min="0" :max="100"> <splitpanes class="default-theme" @resized="storePaneSize" style="height: 400px"> <pane :size="paneSize"> <span>{{ paneSize }}%</span> </pane> <pane :size="100 - paneSize"> <span>{{ 100 - paneSize }}%</span> </pane> </splitpanes>
import { ref } from 'vue'
import { Splitpanes, Pane } from 'splitpanes'
import 'splitpanes/dist/splitpanes.css'

const paneSize = ref(localStorage.paneSize ?? 30) // Read from persistent localStorage.
const storePaneSize = ({ prevPane }) => {
  localStorage.paneSize = prevPane.size // Store in persistent localStorage.
}

const reloadPage = () => window.location.reload() // Button action to reload the page.
import { ref } from 'vue' import { Splitpanes, Pane } from 'splitpanes' import 'splitpanes/dist/splitpanes.css' const paneSize = ref(localStorage.paneSize ?? 30) // Read from persistent localStorage. const storePaneSize = ({ prevPane }) => { localStorage.paneSize = prevPane.size // Store in persistent localStorage. } const reloadPage = () => window.location.reload() // Button action to reload the page.

In-depth reactivity

This example shows the reactivity when you modify anything in your component inside splitpanes.

1
Number is: 0
2
Number is: 0
Number on the left is: 0
Number on the right is: 0
3
Number is: 0
4
- Nested splitpanes -
[0, 0, 0]
<button @click="generateRandomNumber">Generate 3 random numbers</button>
<button @click="incrementNumber(3)">Increment pane #3</button>

<splitpanes horizontal class="default-theme" style="height: 400px">
  <pane>
    <splitpanes>
      <pane v-for="i in 3" :key="i">
        <span>{{ i }}</span><br>
        <em>Number is: {{ randomNums[i] }}</em><br>
        <em v-if="i === 2">
          Number on the left is: {{ randomNums[1] }}<br>
          Number on the right is: {{ randomNums[3] }}<br>
        </em>
        <button(v-if="i !== 2" @click="randomNums[i] = randomNums[i] + 1">+1</button>
      </pane>
    </splitpanes>
  </pane>
  <pane>
    <span>4</span><br>
    <em>
      - Nested splitpanes -<br>
      [{{ randomNums[1] }}, {{ randomNums[2] }}, {{ randomNums[1] }}]
    </em>
  </pane>
</splitpanes>
<button @click="generateRandomNumber">Generate 3 random numbers</button> <button @click="incrementNumber(3)">Increment pane #3</button> <splitpanes horizontal class="default-theme" style="height: 400px"> <pane> <splitpanes> <pane v-for="i in 3" :key="i"> <span>{{ i }}</span><br> <em>Number is: {{ randomNums[i] }}</em><br> <em v-if="i === 2"> Number on the left is: {{ randomNums[1] }}<br> Number on the right is: {{ randomNums[3] }}<br> </em> <button(v-if="i !== 2" @click="randomNums[i] = randomNums[i] + 1">+1</button> </pane> </splitpanes> </pane> <pane> <span>4</span><br> <em> - Nested splitpanes -<br> [{{ randomNums[1] }}, {{ randomNums[2] }}, {{ randomNums[1] }}] </em> </pane> </splitpanes>
import { ref } from 'vue'
import { Splitpanes, Pane } from 'splitpanes'
import 'splitpanes/dist/splitpanes.css'

const randomNums = ref({ 1: 0, 2: 0, 3: 0 })

const generateRandomNumber = () => {
  randomNums.value = Object.assign(randomNums.value, {
    1: Math.round(Math.random() * 100),
    2: Math.round(Math.random() * 100),
    3: Math.round(Math.random() * 100)
  })
}

const incrementNumber = i => {
  randomNums.value[i]++
}
import { ref } from 'vue' import { Splitpanes, Pane } from 'splitpanes' import 'splitpanes/dist/splitpanes.css' const randomNums = ref({ 1: 0, 2: 0, 3: 0 }) const generateRandomNumber = () => { randomNums.value = Object.assign(randomNums.value, { 1: Math.round(Math.random() * 100), 2: Math.round(Math.random() * 100), 3: Math.round(Math.random() * 100) }) } const incrementNumber = i => { randomNums.value[i]++ }

Toggle a pane with v-if

1
2
3
<button @click="hidePane2 = !hidePane2">{{ hidePane2 ? 'Show' : 'Hide' }} Pane 2</button>
<splitpanes class="default-theme" style="height: 400px">
  <pane>
    <span>1</span>
  </pane>
  <pane v-if="!hidePane2">
    <span>2</span>
  </pane>
  <pane>
    <span>3</span>
  </pane>
</splitpanes>
<button @click="hidePane2 = !hidePane2">{{ hidePane2 ? 'Show' : 'Hide' }} Pane 2</button> <splitpanes class="default-theme" style="height: 400px"> <pane> <span>1</span> </pane> <pane v-if="!hidePane2"> <span>2</span> </pane> <pane> <span>3</span> </pane> </splitpanes>

Resizable Drawer

Sometimes, you need a resizable drawer that goes on top of your app.
Here's one way to do this, mostly thanks to CSS powers. The key here is to set the Splitpanes container to pointer-events: none; and reactivate the pointer events in the splitter and drawer so that you can click through Splitpanes on the rest of the page.

<button @click="showDrawer = !showDrawer">
  {{ showDrawer ? 'Hide' : 'Show' }} Drawer
</button>

<splitpanes v-if="showDrawer" class="default-theme">
  <pane></pane>
  <pane size="40">
    <h3>Resizable Drawer</h3>
  </pane>
</splitpanes>
<button @click="showDrawer = !showDrawer"> {{ showDrawer ? 'Hide' : 'Show' }} Drawer </button> <splitpanes v-if="showDrawer" class="default-theme"> <pane></pane> <pane size="40"> <h3>Resizable Drawer</h3> </pane> </splitpanes>
.splitpanes {
  position: fixed;
  inset: 0 0 0 auto;
  z-index: 100;
  pointer-events: none;

  .splitpanes__pane:first-child {background-color: transparent;}
  .splitpanes__splitter {pointer-events: all;}

  .splitpanes__pane ~ .splitpanes__pane {
    pointer-events: all;
    background-color: #fff;
    box-shadow: none;
    align-items: flex-start;
    overflow: hidden;
    white-space: nowrap;
  }
}
.splitpanes { position: fixed; inset: 0 0 0 auto; z-index: 100; pointer-events: none; .splitpanes__pane:first-child {background-color: transparent;} .splitpanes__splitter {pointer-events: all;} .splitpanes__pane ~ .splitpanes__pane { pointer-events: all; background-color: #fff; box-shadow: none; align-items: flex-start; overflow: hidden; white-space: nowrap; } }

Vue Router inside splitpanes

This is another reactivity example of a rather common case: Vue Router inside splitpanes.
The navigation is in the left pane, but you can also access from outside of splitpanes, through those buttons:

Home viewAnother view
I have a min width of 20%
router-view
3
<button to="home-view">Home view</button>
<button to="another-view">Another view</button>

<splitpanes horizontal class="default-theme" style="height: 400px">
  <pane min-size="20">
    <p>Navigation</p>
    <ul>
      <li><router-link to="home-view">Home view</li>
      <li><router-link to="another-view">Another view</li>
    </ul>
  </pane>
  <pane>
    <em>router-view</em>
    <router-view />
  </pane>
  <pane>
    <span>3</span>
  </pane>
</splitpanes>
<button to="home-view">Home view</button> <button to="another-view">Another view</button> <splitpanes horizontal class="default-theme" style="height: 400px"> <pane min-size="20"> <p>Navigation</p> <ul> <li><router-link to="home-view">Home view</li> <li><router-link to="another-view">Another view</li> </ul> </pane> <pane> <em>router-view</em> <router-view /> </pane> <pane> <span>3</span> </pane> </splitpanes>
// Vue Router routes.
routes: [
  {
    path: '/home-view',
    component: () => import('./components/home-view.vue')
  },
  {
    path: '/another-view',
    component: () => import('./components/another-view.vue')
  }
]
// Vue Router routes. routes: [ { path: '/home-view', component: () => import('./components/home-view.vue') }, { path: '/another-view', component: () => import('./components/another-view.vue') } ]
<template>
  <div class="green">
    <div>This is home</div>
  </div>
</template>
<template> <div class="green"> <div>This is home</div> </div> </template>

Listening to emitted events

Splitpanes fires several events that you can listen to. Here's a quick list, but you can also check the Emitted Events section for more details.

  • ready: When the component is ready.
  • resize: When a pane is being resized.
  • resized: When a pane has been resized.
  • pane-click: When a pane is clicked.
  • pane-maximize: When a pane is maximized.
  • pane-add: When a pane is added.
  • pane-remove: When a pane is removed.
  • splitter-click: When a splitter is clicked.
  • splitter-dblclick: When a splitter is double clicked.

Try resizing panes and check the logs bellow.

1
2
3
// Event name: Event params   (Last event on top)
ready: {"panes":[{"min":10,"max":100,"size":33.333333333333336},{"min":10,"max":100,"size":33.333333333333336},{"min":10,"max":100,"size":33.333333333333336}]}
<splitpanes
  class="default-theme"
  @resize="log('resize', $event)"
  @resized="log('resized', $event)"
  @pane-maximize="log('pane-maximize', $event)"
  @pane-click="log('pane-click', $event)"
  @ready="log('ready', $event)"
  @splitter-click="log('splitter-click', $event)"
  style="height: 400px">
  <pane v-for="i in 3" :key="i" min-size="10">
    <span>{{ i }}</span>
  </pane>
</splitpanes>
<splitpanes class="default-theme" @resize="log('resize', $event)" @resized="log('resized', $event)" @pane-maximize="log('pane-maximize', $event)" @pane-click="log('pane-click', $event)" @ready="log('ready', $event)" @splitter-click="log('splitter-click', $event)" style="height: 400px"> <pane v-for="i in 3" :key="i" min-size="10"> <span>{{ i }}</span> </pane> </splitpanes>

Increased reactive touch zone for touch devices

Try it yourself on Codepen

1
2
3

In this example the splitters are thin lines but the reactive touch zone is spread to 30 pixels all around! Hover a splitter to see the enlarged fat-finger-proof reactive zone.

<splitpanes horizontal style="height: 400px">
  <pane>
    <splitpanes>
      <pane>
        <span>1</span>
      </pane>
      <pane>
        <span>2</span>
      </pane>
      <pane>
        <span>3</span>
      </pane>
    </splitpanes>
  </pane>
  <pane>
    <p>In this example the splitters are thin lines but the reactive touch zone is spread to 30 pixels all around!</p>
  </pane>
</splitpanes>
<splitpanes horizontal style="height: 400px"> <pane> <splitpanes> <pane> <span>1</span> </pane> <pane> <span>2</span> </pane> <pane> <span>3</span> </pane> </splitpanes> </pane> <pane> <p>In this example the splitters are thin lines but the reactive touch zone is spread to 30 pixels all around!</p> </pane> </splitpanes>
.splitpanes {background-color: #f8f8f8;}

.splitpanes__splitter {background-color: #ccc;position: relative;}
.splitpanes__splitter:before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  transition: opacity 0.4s;
  background-color: rgba(255, 0, 0, 0.3);
  opacity: 0;
  z-index: 1;
}
.splitpanes__splitter:hover:before {opacity: 1;}
.splitpanes--vertical > .splitpanes__splitter:before {left: -30px;right: -30px;height: 100%;}
.splitpanes--horizontal > .splitpanes__splitter:before {top: -30px;bottom: -30px;width: 100%;}
.splitpanes {background-color: #f8f8f8;} .splitpanes__splitter {background-color: #ccc;position: relative;} .splitpanes__splitter:before { content: ''; position: absolute; left: 0; top: 0; transition: opacity 0.4s; background-color: rgba(255, 0, 0, 0.3); opacity: 0; z-index: 1; } .splitpanes__splitter:hover:before {opacity: 1;} .splitpanes--vertical > .splitpanes__splitter:before {left: -30px;right: -30px;height: 100%;} .splitpanes--horizontal > .splitpanes__splitter:before {top: -30px;bottom: -30px;width: 100%;}

Do your own style

If you don't want to use the default style, here is how to do your own.

Try it yourself on Codepen

1
2
3
4
<splitpanes horizontal style="height: 400px">
  <pane>
    <splitpanes vertical>
      <pane>
        <span>1</span>
      </pane>
      <pane>
        <span>2</span>
      </pane>
      <pane>
        <span>3</span>
      </pane>
    </splitpanes>
  </pane>
  <pane>
    <span>4</span>
  </pane>
</splitpanes>
<splitpanes horizontal style="height: 400px"> <pane> <splitpanes vertical> <pane> <span>1</span> </pane> <pane> <span>2</span> </pane> <pane> <span>3</span> </pane> </splitpanes> </pane> <pane> <span>4</span> </pane> </splitpanes>
.splitpanes {
  background: linear-gradient(-45deg, #EE7752, #E73C7E, #23A6D5, #23D5AB);
}

.splitpanes__pane {
  box-shadow: 0 0 5px rgba(0, 0, 0, .2) inset;
  justify-content: center;
  align-items: center;
  display: flex;
}

.splitpanes--vertical > .splitpanes__splitter {
  min-width: 6px;
  background: linear-gradient(90deg, #ccc, #111);
}

.splitpanes--horizontal > .splitpanes__splitter {
  min-height: 6px;
  background: linear-gradient(0deg, #ccc, #111);
}
.splitpanes { background: linear-gradient(-45deg, #EE7752, #E73C7E, #23A6D5, #23D5AB); } .splitpanes__pane { box-shadow: 0 0 5px rgba(0, 0, 0, .2) inset; justify-content: center; align-items: center; display: flex; } .splitpanes--vertical > .splitpanes__splitter { min-width: 6px; background: linear-gradient(90deg, #ccc, #111); } .splitpanes--horizontal > .splitpanes__splitter { min-height: 6px; background: linear-gradient(0deg, #ccc, #111); }

API

Here is the list of all the props.

  • horizontalDefault: false

    The orientation of the panes splitting.
    Vertical by default, meaning the splitters are vertical, but you can resize horizontally

  • push-other-panesDefault: true

    Whether it should push the next splitter when dragging a splitter until it reached another one.

  • dbl-click-splitterDefault: true

    Double click on splitter to maximize the next pane.

  • rtlDefault: false

    Supports Right to left direction.

  • first-splitterDefault: false

    Displays the first splitter when set to true. This allows maximizing the first pane on splitter double click.

Emitted Events

Here is the list of events that are emitted from splitpanes along with their parameters.
View them in action in the Listening to emitted events example.

  • readyFires when splitpanes is ready. Returns an object containing:

    • panes: an array of all the panes objects with their dimensions.
  • resizeFires while resizing (on mousemove/touchmove). Returns an object containing:

    • event: the native JavaScript event.
    • index: the index of the resizing splitter. The counter always starts from zero.
    • prevPane: the object of the previous pane (on the left if ltr, on the right if rtl, above if horizontal layout) from the splitter with its dimensions and DOM element.
    • nextPane: the object of the next pane (on the right if ltr, on the left if rtl, below if horizontal layout) from the splitter with its dimensions and DOM element.
    • panes: an array of all the panes objects with their dimensions.
  • resizedFires after resizing (on mousemove/touchmove), or also after the free space redistribution occurring after adding or removing a pane. Returns an object containing:

    • event: the native JavaScript event.
    • index: the index of the resizing splitter. The counter always starts from zero.
    • prevPane: the object of the previous pane (on the left if ltr, on the right if rtl, above if horizontal layout) from the splitter with its dimensions and DOM element.
    • nextPane: the object of the next pane (on the right if ltr, on the left if rtl, below if horizontal layout) from the splitter with its dimensions and DOM element.
    • panes: an array of all the panes objects with their dimensions.
  • pane-clickFires on pane click/tap. Returns an object containing:

    • event: the native JavaScript event.
    • index: the index of the pane. The counter starts from zero.
    • pane: the clicked pane object with its dimensions and DOM element.
    • panes: an array of all the panes objects with their dimensions.
  • pane-maximizeFires on splitter double click/tap. Returns an object containing:

    • event: the native JavaScript event.
    • index: the index of the pane. The counter starts from zero.
    • pane: the maximized pane object with its dimensions and DOM element.
    • panes: an array of all the panes objects with their dimensions.
  • pane-addFires on added pane. Returns an object containing:

    • event: the native JavaScript event.
    • pane: the added pane object with its dimensions and DOM element.
    • panes: an array of all the panes objects with their dimensions.
  • pane-removeFires on removed pane. Returns an object containing:

    • event: the native JavaScript event.
    • pane: the removed pane object with its dimensions.
    • panes: an array of all the panes objects with their dimensions.
  • splitter-clickReturns the next pane object (with its dimensions) directly after the clicked splitter.
    This event is only emitted if dragging did not occur between mousedown and mouseup.

    • event: the native JavaScript event.
    • index: the index of the resizing splitter. The counter always starts from zero.
    • prevPane: the object of the previous pane (on the left if ltr, on the right if rtl, above if horizontal layout) from the splitter with its dimensions and DOM element.
    • nextPane: the object of the next pane (on the right if ltr, on the left if rtl, below if horizontal layout) from the splitter with its dimensions and DOM element.
    • panes: an array of all the panes objects with their dimensions.
  • splitter-dblclickFires when the user double clicks a splitter and returns the an object containing

    • event: the native JavaScript event.
    • index: the index of the resizing splitter. The counter always starts from zero.
    • prevPane: the object of the previous pane (on the left if ltr, on the right if rtl, above if horizontal layout) from the splitter with its dimensions and DOM element.
    • nextPane: the object of the next pane (on the right if ltr, on the left if rtl, below if horizontal layout) from the splitter with its dimensions and DOM element.
    • panes: an array of all the panes objects with their dimensions.

Release Notes

Version 4.0.0
  • Emit splitter-dblclick on splitter dblclick event. (#120, #181, #182, #183)
  • Renamed dblClickSplitter to maximizePanes, and still on by default on splitter double click.
  • Refactored all the emitted events to always return a single object containing as much information as possible. E.g. event, index, pane, prevPane, nextPane, panes.
Version 3.2.0
  • Account for cursor position when dragging a splitter. (#204)
  • Components fully rewritten with Composition API. Faster and more efficient resizing.
Version 3.0.0 For Vue 3 projects.

Installing the latest splitpanes on a Vue 2 project will break it.
For Vue 2, you need to install splitpanes from the legacy tag: npm i splitpanes@legacy.

Version 2.3.5 Prevent splitter double taps on touch devices if `dblClickSplitter` is set to false.
Version 2.3.4 Fix removing pane DOM nodes in IE11
Version 2.3.1 Fix firing `pane-click` event on pane click
Version 2.3.0 Support rtl direction
Version 2.2.0
Version 2.0.0 Fix reactivity issues.

  • Children must now be wrapped into a `pane` component.
  • The attribute `splitpanes-size` is now replaced with `size` on the `pane` component.
  • you can still add CSS classes on the `pane` component tag.

Version 1.14.0 Programmatically set pane size
Version 1.13.0 Emit event on splitter click
Version 1.12.0 double click splitter to maximize is now an option
Version 1.11.0 Persist panes size after slots changed
Version 1.10.0 Add maximum size feature on panes
Version 1.9.0 Emit event on resize & watch slots optional

  • The `resize` event - previously firing after resize end - is now firing on resize.
    A new `resized` event is emitted on resize end. Check out the Listening to emitted events example.
  • By default and for performance, the reactivity is now limited to slot deletion and slot creation.
    With the option `watchSlots` you can also track any change on the slots.

Version 1.8.0 Watch slots
Version 1.7.0 Double click splitter to maximize next pane
Version 1.6.0 Emit events
Version 1.5.0 Add default size feature on panes
Version 1.4.0 Add minimum size feature on panes
Version 1.3.0 Splitpanes slots are now reactive (add/remove on the fly)
Version 1.2.0 Add a `default-theme` CSS class to load default theme
Version 1.1.0 Allow pushing other panes while dragging splitter
Version 1.0.0 First public release