Splitter
A splitter divides an area into panels that people resize by dragging the handle between them, or with the keyboard.
Folders
Messages
<tk-splitter style="block-size: 160px"> <tk-splitter-panel size="30" min="15" max="60"><p>Folders</p></tk-splitter-panel> <tk-splitter-handle label="Resize folders"></tk-splitter-handle> <tk-splitter-panel><p>Messages</p></tk-splitter-panel> </tk-splitter>
Anatomy
| Part | What it is |
|---|---|
tk-splitter |
the group; lays out its panels along one axis and keeps their sizes |
tk-splitter-panel |
one panel; holds anything and clips what overflows |
tk-splitter-handle |
the line between two panels, with a 12px drag area; one Tab stop |
Panels and handles are direct children of the group, in order: panel, handle, panel, and so on. A handle resizes only the two panels next to it.
Orientation and nesting
orientation="horizontal" (default) puts panels side by side. orientation="vertical"
stacks them. For a two-way layout, put a group inside a panel.
Files
Editor
Console
<tk-splitter style="block-size: 240px">
<tk-splitter-panel size="25" min="15"><p>Files</p></tk-splitter-panel>
<tk-splitter-handle label="Resize files"></tk-splitter-handle>
<tk-splitter-panel><tk-splitter orientation="vertical" style="block-size: 100%">
<tk-splitter-panel size="70"><p>Editor</p></tk-splitter-panel>
<tk-splitter-handle label="Resize console"></tk-splitter-handle>
<tk-splitter-panel min="10"><p>Console</p></tk-splitter-panel>
</tk-splitter></tk-splitter-panel>
</tk-splitter>Give the group its size, such as a block-size or a grid track; the panels divide it.
Sizes
Sizes are percentages of the group.
size: the panel's starting share. Panels without one share what's left equally. After that, the splitter keeps the sizes as people drag.minandmax: the share a panel can't go below or above. A drag stops where either neighbor hits its limit, and the limits also hold when the window resizes.minis 0 by default, so set a floor where content must stay usable.- Double-click a handle to reset its two panels to their starting split.
Saving a layout
tk-resize fires on the group after every change a person makes, with detail.sizes.
Read the sizes from sizes and restore them with setSizes(), which keeps each panel
within its limits and doesn't fire tk-resize.
const splitter = document.querySelector('tk-splitter');
splitter.addEventListener('tk-resize', debounce(() => {
localStorage.setItem('layout', JSON.stringify(splitter.sizes));
}, 200));
const saved = localStorage.getItem('layout');
if (saved) splitter.setSizes(JSON.parse(saved));States
Fixed sidebar
Content
<tk-splitter style="block-size: 120px"> <tk-splitter-panel size="30"><p>Fixed sidebar</p></tk-splitter-panel> <tk-splitter-handle label="Resize sidebar" disabled></tk-splitter-handle> <tk-splitter-panel><p>Content</p></tk-splitter-panel> </tk-splitter>
On hover and while dragging, a 2px accent bar appears on the line. Keyboard focus shows a ring around the handle's drag area.
disabled: locks the two panels. The handle becomes a plain line that can't be dragged or focused.
When to use
- Use a splitter when the right split depends on the person and the task: navigation and content, editor and preview, list and detail, main area and console.
- Use plain layout when nobody needs to change the split. Every handle is one more control to understand.
- Don't use it to show or hide an area. A panel dragged to zero isn't closed; use a real toggle.
Content
- Name each handle by what it resizes: "Resize sidebar", "Resize console". The default name is "Resize", which can't tell several handles apart.
- Scroll inside your panel content when it can outgrow the panel, such as with a
Scroll area ; the panel itself clips. - Keep controls a few pixels from the handle. Its drag area covers about 5px of each panel's edge.
Do / Don't
| ✅ Do | ❌ Don't |
|---|---|
| Use it where people need different splits | Add handles to a layout nobody adjusts |
| Name each handle by what it resizes | Leave several handles named "Resize" |
Set min where content stops being usable |
Let a panel shrink to nothing by accident |
| Nest groups for a two-way layout | Expect one handle to move more than its two panels |
Save with tk-resize and restore with setSizes() |
Treat a panel dragged to zero as closed |
Related
Slider : sets a value on a scale; a splitter shares space.Divider : a line that doesn't move.Scroll area : scrolling content inside a panel.
API
tk-splitter attributes
| Attribute | Type | Default | What it does |
|---|---|---|---|
orientation |
horizontal | vertical |
horizontal |
panels side by side or stacked |
tk-splitter-panel attributes
| Attribute | Type | Default | What it does |
|---|---|---|---|
size |
number | an equal share of what's left | the starting share, % |
min |
number | 0 |
the smallest share, % |
max |
number | 100 |
the largest share, % |
tk-splitter-handle attributes
| Attribute | Type | Default | What it does |
|---|---|---|---|
label |
string | Resize |
the accessible name; make it distinct per handle |
disabled |
boolean | false |
locks the pair; the handle becomes a plain line |
Slots
| Element | Slot | Content |
|---|---|---|
tk-splitter |
default | panels and handles, in order |
tk-splitter-panel |
default | anything, including a nested tk-splitter |
Properties and methods
| Member | What it does |
|---|---|
tk-splitter.sizes |
read-only; the current shares in %, in order |
tk-splitter.setSizes(sizes) |
sets the shares, kept within each panel's limits; doesn't fire tk-resize |
Events
tk-splitter fires tk-resize after every drag step, key press, or double-click reset,
with detail.sizes. It bubbles. setSizes() doesn't fire it.
CSS
--tk-splitter-handle-hitontk-splitter-handle: the width of the drag area, 12px by default. It overlays the panels and takes no space.
Tokens
| Element | Token |
|---|---|
| line | border/default, 1px |
| hover and drag bar | border/accent, 2px |
| focus ring | border/accent/focus, with radius-2 |
| disabled line | border/subtle |
The cursor is col-resize in a horizontal group and row-resize in a vertical one.
Values per theme:
Accessibility
Built in:
- The handle is a focusable separator, announced with its name and the size of the panel before it: "Resize sidebar, separator, 30%". Every step is announced.
- A disabled handle leaves the Tab order and is announced as a plain separator.
- Touch drags on the handle don't scroll the page.
Your part:
- Give each handle a distinct
label. - Set
minso a keyboard user can't shrink a panel until its content is unusable. - On touch-heavy screens, widen the drag area with
--tk-splitter-handle-hit.
| Key | Action |
|---|---|
Tab |
moves focus to the handle |
Right / Down |
grows the panel before the handle by 1% |
Left / Up |
shrinks it by 1% |
Shift + arrow |
the same, by 10% |
Home / End |
shrinks it to its smallest or grows it to its largest |