Starting Point
v0.36.0

Search documentation

Search for a page and jump to it.

Start typing to search...
Go to Page
escClose

Tailwind CSS Resizable Panels

Use the resizable component to split a layout into panels the user drags to size, like a sidebar next to content or an editor beside its preview. For a navigation column that collapses to icons, use the sidebar.

<div class="resizable max-w-md rounded-lg border">
  <div class="resizable-panel" data-sp-size="50">
    <div class="flex h-60 items-center justify-center p-6">
      <span class="font-semibold">One</span>
    </div>
  </div>
  <div class="resizable-handle"><div class="resizable-grip"></div></div>
  <div class="resizable-panel" data-sp-size="50">
    <div class="resizable resizable-vertical">
      <div class="resizable-panel" data-sp-size="25">
        <div class="flex h-full items-center justify-center p-6">
          <span class="font-semibold">Two</span>
        </div>
      </div>
      <div class="resizable-handle"><div class="resizable-grip"></div></div>
      <div class="resizable-panel" data-sp-size="75">
        <div class="flex h-full items-center justify-center p-6">
          <span class="font-semibold">Three</span>
        </div>
      </div>
    </div>
  </div>
</div>

Usage

Add the resizable class to a container with a height, and put resizable-panel elements inside it with a resizable-handle between each pair. Add resizable-vertical to the container to stack the panels instead, and put a resizable-grip inside a handle to show a visible grip. Nest a group inside a panel to split both ways.

ClassDescription
resizableAdd to the container, which carries the data-sp-* options for the group
resizable-verticalAdd to resizable to stack the panels and drag up and down
resizable-panelAdd to each panel, which carries its own data-sp-* size options
resizable-handleAdd to the element between two panels that drags the split
resizable-gripAdd to an element inside a handle for a visible grip
<div class="resizable h-48">
  <div class="resizable-panel">One</div>
  <div class="resizable-handle"></div>
  <div class="resizable-panel">Two</div>
</div>

Examples

Vertical resizable panels

Add resizable-vertical to stack the panels and drag the split up and down.

<div class="resizable resizable-vertical min-h-60 max-w-md rounded-lg border">
  <div class="resizable-panel" data-sp-size="25">
    <div class="flex h-full items-center justify-center p-6">
      <span class="font-semibold">Header</span>
    </div>
  </div>
  <div class="resizable-handle"></div>
  <div class="resizable-panel" data-sp-size="75">
    <div class="flex h-full items-center justify-center p-6">
      <span class="font-semibold">Content</span>
    </div>
  </div>
</div>

Handle with a grip

Put a resizable-grip inside the handle to show where to drag.

<div class="resizable min-h-60 max-w-md rounded-lg border">
  <div class="resizable-panel" data-sp-size="25">
    <div class="flex h-full items-center justify-center p-6">
      <span class="font-semibold">Sidebar</span>
    </div>
  </div>
  <div class="resizable-handle"><div class="resizable-grip"></div></div>
  <div class="resizable-panel" data-sp-size="75">
    <div class="flex h-full items-center justify-center p-6">
      <span class="font-semibold">Content</span>
    </div>
  </div>
</div>

Panel sizes

Set a panel's starting size with data-sp-size and its limits with data-sp-min and data-sp-max, as a percentage or in px, rem, em, vh, or vw.

<div class="resizable min-h-60 max-w-md rounded-lg border">
  <div class="resizable-panel" data-sp-size="30" data-sp-min="120px" data-sp-max="50">
    <div class="flex h-full items-center justify-center p-6 text-center text-sm">
      <span class="font-semibold">Min 120px, max 50%</span>
    </div>
  </div>
  <div class="resizable-handle"><div class="resizable-grip"></div></div>
  <div class="resizable-panel" data-sp-min="25">
    <div class="flex h-full items-center justify-center p-6 text-sm">
      <span class="font-semibold">Min 25%</span>
    </div>
  </div>
</div>

Collapsible panel

Add data-sp-collapsible to let a panel snap shut when dragged past half its minimum, and data-sp-collapsed-size to leave a sliver showing.

<div class="resizable min-h-60 max-w-md rounded-lg border">
  <div class="resizable-panel" data-sp-size="30" data-sp-min="20" data-sp-collapsible data-sp-collapsed-size="8">
    <div class="flex h-full items-center justify-center p-6">
      <span class="font-semibold">Sidebar</span>
    </div>
  </div>
  <div class="resizable-handle"><div class="resizable-grip"></div></div>
  <div class="resizable-panel">
    <div class="flex h-full items-center justify-center p-6">
      <span class="font-semibold">Content</span>
    </div>
  </div>
</div>

Remember the layout

Add data-sp-persist with a key to store the layout in the browser and restore it on the next visit.

<div class="resizable min-h-60 max-w-md rounded-lg border" data-sp-persist="docs-demo">
  <div class="resizable-panel" data-sp-size="40">
    <div class="flex h-full items-center justify-center p-6">
      <span class="font-semibold">Files</span>
    </div>
  </div>
  <div class="resizable-handle"><div class="resizable-grip"></div></div>
  <div class="resizable-panel" data-sp-size="60">
    <div class="flex h-full items-center justify-center p-6">
      <span class="font-semibold">Editor</span>
    </div>
  </div>
</div>

RTL

Add dir="rtl" to any parent element, typically <html>, to render right-to-left. See the RTL guide for details.

<div id="resizable-rtl-demo" class="resizable max-w-md rounded-lg border" dir="rtl">
  <div class="resizable-panel" data-sp-size="50">
    <div class="flex h-60 items-center justify-center p-6">
      <span class="font-semibold" data-i18n="one">واحد</span>
    </div>
  </div>
  <div class="resizable-handle"><div class="resizable-grip"></div></div>
  <div class="resizable-panel" data-sp-size="50">
    <div class="resizable resizable-vertical">
      <div class="resizable-panel" data-sp-size="25">
        <div class="flex h-full items-center justify-center p-6">
          <span class="font-semibold" data-i18n="two">اثنان</span>
        </div>
      </div>
      <div class="resizable-handle"><div class="resizable-grip"></div></div>
      <div class="resizable-panel" data-sp-size="75">
        <div class="flex h-full items-center justify-center p-6">
          <span class="font-semibold" data-i18n="three">ثلاثة</span>
        </div>
      </div>
    </div>
  </div>
</div>
 
<script>
  const translations = {
    ar: { dir: "rtl", one: "واحد", two: "اثنان", three: "ثلاثة" },
    he: { dir: "rtl", one: "אחד", two: "שניים", three: "שלושה" },
    en: { dir: "ltr", one: "One", two: "Two", three: "Three" },
  };
  window.addEventListener("message", (e) => {
    const t = translations[e.data?.lang];
    if (e.data?.type !== "sp-language" || !t) return;
    document.getElementById("resizable-rtl-demo").dir = t.dir;
    document.querySelectorAll("[data-i18n]").forEach((el) => {
      el.textContent = t[el.dataset.i18n];
    });
  });
</script>

Options

Set group options on the resizable element and size options on each resizable-panel. Sizes are a percentage of the group, or a length in px, rem, em, vh, or vw.

AttributeOnValuesDefault
data-sp-persistgroupStorage keyNone
data-sp-disabledgroupBooleanfalse
data-sp-sizepanelSizeAn equal share
data-sp-minpanelSize0
data-sp-maxpanelSize100
data-sp-collapsiblepanelBooleanfalse
data-sp-collapsed-sizepanelSize0
data-sp-disabledpanelBooleanfalse
data-sp-preserve-pixelspanelBooleanfalse
<div class="resizable h-64" data-sp-persist="workspace">
  <div class="resizable-panel" data-sp-size="240px" data-sp-min="160px" data-sp-collapsible data-sp-preserve-pixels>
    Sidebar
  </div>
  <div class="resizable-handle"></div>
  <div class="resizable-panel">Content</div>
</div>

A collapsed panel carries the collapsed class. A disabled panel keeps its size, so the handles next to it stop dragging. A panel with data-sp-preserve-pixels keeps its pixel width when the group changes size, while the other panels share the difference. A double click on a handle puts a neighbor back to its data-sp-size.

JavaScript

Events

Events fire on the resizable element. sp-resize fires on every change, sp-resized once a drag ends or a key press lands, both with { layout } as percentages. The collapse events carry { panel, index }.

EventWhen
sp-resizeThe layout is changing
sp-resizedThe layout settled
sp-collapseA collapsible panel collapsed
sp-expandA collapsed panel expanded
el.addEventListener("sp-resized", (e) => {
  console.log(e.detail.layout);
});

Methods

Get the instance with sp.resizable(el), then call its methods. A panel is its index or its element.

MethodDescription
layout()The current sizes as percentages
setLayout(sizes)Apply an array of sizes, scaled to fill the group
resize(panel, size)Size one panel in any unit, its neighbor takes the rest
collapse(panel)Collapse a collapsible panel
expand(panel)Expand a collapsed panel to its last size
isCollapsed(panel)Whether the panel is collapsed
const group = sp.resizable(document.querySelector("#workspace"));
 
group.resize(0, "320px");