Resizable

ui-resizable is a flex container for ui-resizable-panel elements separated by ui-resizable-handle elements. Each panel's size is its share of the group. Dragging a handle, or focusing it and pressing the arrow keys, moves size from one neighbouring panel to the other, never below either panel's min. The group is as wide as its container. Give it a height in spacing units (or size its parent), and add variant="outline" for a border.

Previewindex.html
One
Two
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Resizable demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
  <style>
    .demo-medium {
      width: min(100%, calc(var(--spacing) * 120));
    }
    .demo-tile {
      display: grid;
      place-items: center;
      box-sizing: border-box;
      height: 100%;
      min-height: calc(var(--spacing) * 16);
      padding: calc(var(--spacing) * 4);
      border-radius: var(--radius-lg);
      background: var(--muted);
      font-size: var(--text-sm);
      font-weight: var(--font-weight-medium);
    }
  </style>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/resizable.html"></import-element>

  <div class="demo-medium">
  <ui-resizable variant="outline" height="48">
    <ui-resizable-panel size="50">
      <div class="demo-tile">One</div>
    </ui-resizable-panel>
    <ui-resizable-handle></ui-resizable-handle>
    <ui-resizable-panel size="50">
      <div class="demo-tile">Two</div>
    </ui-resizable-panel>
  </ui-resizable>
  </div>
</body>
</html>

Examples

Vertical

direction="vertical" stacks the panels. Drag the handle up and down, or use the Up and Down arrows.

Previewindex.html
Header
Content
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Resizable demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
  <style>
    .demo-narrow {
      width: min(100%, calc(var(--spacing) * 88));
    }
    .demo-tile {
      display: grid;
      place-items: center;
      box-sizing: border-box;
      height: 100%;
      min-height: calc(var(--spacing) * 16);
      padding: calc(var(--spacing) * 4);
      border-radius: var(--radius-lg);
      background: var(--muted);
      font-size: var(--text-sm);
      font-weight: var(--font-weight-medium);
    }
  </style>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/resizable.html"></import-element>

  <div class="demo-narrow">
  <ui-resizable direction="vertical" variant="outline" height="64">
    <ui-resizable-panel size="30">
      <div class="demo-tile">Header</div>
    </ui-resizable-panel>
    <ui-resizable-handle></ui-resizable-handle>
    <ui-resizable-panel size="70">
      <div class="demo-tile">Content</div>
    </ui-resizable-panel>
  </ui-resizable>
  </div>
</body>
</html>

Visible grip

Add handle to a handle to draw a grip on it, which makes the drag target easier to see.

Previewindex.html
Sidebar
Content
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Resizable demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
  <style>
    .demo-medium {
      width: min(100%, calc(var(--spacing) * 120));
    }
    .demo-tile {
      display: grid;
      place-items: center;
      box-sizing: border-box;
      height: 100%;
      min-height: calc(var(--spacing) * 16);
      padding: calc(var(--spacing) * 4);
      border-radius: var(--radius-lg);
      background: var(--muted);
      font-size: var(--text-sm);
      font-weight: var(--font-weight-medium);
    }
  </style>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/resizable.html"></import-element>

  <div class="demo-medium">
  <ui-resizable variant="outline" height="40">
    <ui-resizable-panel size="25" min="15">
      <div class="demo-tile">Sidebar</div>
    </ui-resizable-panel>
    <ui-resizable-handle handle></ui-resizable-handle>
    <ui-resizable-panel size="75" min="40">
      <div class="demo-tile">Content</div>
    </ui-resizable-panel>
  </ui-resizable>
  </div>
</body>
</html>

Nested groups

A panel can hold another group in the other direction.

Previewindex.html
One
Two
Three
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Resizable demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
  <style>
    .demo-medium {
      width: min(100%, calc(var(--spacing) * 120));
    }
    .demo-tile {
      display: grid;
      place-items: center;
      box-sizing: border-box;
      height: 100%;
      min-height: calc(var(--spacing) * 16);
      padding: calc(var(--spacing) * 4);
      border-radius: var(--radius-lg);
      background: var(--muted);
      font-size: var(--text-sm);
      font-weight: var(--font-weight-medium);
    }
  </style>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/resizable.html"></import-element>

  <div class="demo-medium">
  <ui-resizable variant="outline" height="56">
    <ui-resizable-panel size="40">
      <div class="demo-tile">One</div>
    </ui-resizable-panel>
    <ui-resizable-handle handle></ui-resizable-handle>
    <ui-resizable-panel size="60">
      <ui-resizable direction="vertical">
        <ui-resizable-panel size="25">
          <div class="demo-tile">Two</div>
        </ui-resizable-panel>
        <ui-resizable-handle handle></ui-resizable-handle>
        <ui-resizable-panel size="75">
          <div class="demo-tile">Three</div>
        </ui-resizable-panel>
      </ui-resizable>
    </ui-resizable-panel>
  </ui-resizable>
  </div>
</body>
</html>

API

Attributes

ui-resizable

Attribute Type Default Description
direction "horizontal" | "vertical" "horizontal" Lays the panels out in a row or a column. Handles read it when they connect.
height number none Height in spacing units, so height="48" is calc(var(--spacing) * 48). Without it the group fills its parent's height.
variant "default" | "outline" "default" outline adds a 1px border and var(--radius-lg) corners.

ui-resizable-panel

Attribute Type Default Description
size number 50 The panel's share of the group, used as its flex-grow. Between 0 and 100. Make the sizes in a group add up to 100 so they read as percentages. Updated while resizing.
min number 10 The smallest size a handle can shrink the panel to. At least 0.

ui-resizable-handle

Attribute Type Default Description
handle boolean false Shows a visible grip in the middle of the handle.

Properties and methods

ui-resizable-panel exposes size and min as properties. Set size from script to resize a panel. The handles read both properties from the panels on either side.

Parts

Part Slot Renders
ui-resizable-panel (default) One panel. Its content scrolls when it overflows.
ui-resizable-handle (default) A separator between two panels that resizes them.

Panels and handles alternate in the default slot of ui-resizable. The default slot of a panel takes any content, including another ui-resizable.

CSS parts

Part Element Description
grip ui-resizable-handle The grip shown with the handle attribute.

CSS states and custom properties

Accessibility

Edit this page on GitHub · View as Markdown