> Markdown version of [Split Layout](https://vaadin.com/docs/next/components/split-layout). Section index: [llms.txt](https://vaadin.com/docs/next/components/llms.txt)

# Split Layout

Split Layout is a component with two content areas and a draggable split handle between them.

**Lit** — `split-layout-basic.ts`

```html
<vaadin-split-layout style="max-height: 280px;">
  <master-content></master-content>
  <detail-content></detail-content>
</vaadin-split-layout>
```

**Flow** — `SplitLayoutBasic.java`

```java
MasterContent master = new MasterContent();
DetailContent detail = new DetailContent();

SplitLayout splitLayout = new SplitLayout(master, detail);
```

**React** — `split-layout-basic.tsx`

```tsx
<SplitLayout style={{ maxHeight: '280px' }}>
  <MasterContent />
  <DetailContent />
</SplitLayout>
```

## <a id="orientation"></a>Orientation

The default orientation is horizontal, placing the content areas side by side. The orientation can also be vertical.

Orientation should be set based on the content and the screen size. The user can also be allowed to choose which orientation they want to use.

**Lit** — `split-layout-orientation.ts`

```html
<vaadin-split-layout style="max-height: 350px;" orientation="vertical">
  <master-content></master-content>
  <detail-content></detail-content>
</vaadin-split-layout>
```

**Flow** — `SplitLayoutOrientation.java`

```java
MasterContent master = new MasterContent();
DetailContent detail = new DetailContent();

SplitLayout splitLayout = new SplitLayout(master, detail);
splitLayout.setOrientation(SplitLayout.Orientation.VERTICAL);
```

**React** — `split-layout-orientation.tsx`

```tsx
<SplitLayout style={{ maxHeight: '350px' }} orientation="vertical">
  <MasterContent />
  <DetailContent />
</SplitLayout>
```

## <a id="splitter-position"></a>Splitter Position

The initial splitter position is determined by the default size of the two content area components. Their height and width affect the position when using a vertical and horizontal orientation, respectively.

The initial split position can also be explicitly set using a percentage value. When using vertical orientation, the split layout must have an explicit height for this to work. This can be either an absolute or a percentage value. When using a percentage value, ensure that ancestors have an explicit height as well.

**Lit** — `split-layout-initial-splitter-position.ts`

```html
<vaadin-split-layout style="max-height: 280px;">
  <master-content style="width: 70%;"></master-content>
  <detail-content style="width: 30%;"></detail-content>
</vaadin-split-layout>
```

**Flow** — `SplitLayoutInitialSplitterPosition.java`

```java
MasterContent master = new MasterContent();
DetailContent detail = new DetailContent();

SplitLayout splitLayout = new SplitLayout(master, detail);
// Sets the width for the first child to 70%, giving
// the second child the remaining width of 30%
splitLayout.setSplitterPosition(70);
```

**React** — `split-layout-initial-splitter-position.tsx`

```tsx
<SplitLayout style={{ maxHeight: '280px' }}>
  <MasterContent style={{ width: '70%' }} />
  <DetailContent style={{ width: '30%' }} />
</SplitLayout>
```

The splitter respects the minimum and maximum size of the content area components.

**Lit** — `split-layout-min-max-size.ts`

```html
<vaadin-split-layout style="max-height: 280px;">
  <master-content style="min-width: 200px; max-width: 400px;"></master-content>
  <detail-content></detail-content>
</vaadin-split-layout>
```

**Flow** — `SplitLayoutMinMaxSize.java`

```java
MasterContent master = new MasterContent();
master.setMinWidth("200px");
master.setMaxWidth("400px");

DetailContent detail = new DetailContent();

SplitLayout splitLayout = new SplitLayout(master, detail);
```

**React** — `split-layout-min-max-size.tsx`

```tsx
<SplitLayout style={{ maxHeight: '280px' }}>
  <MasterContent style={{ minWidth: '200px', maxWidth: '400px' }} />
  <DetailContent />
</SplitLayout>
```

The split can be adjusted programmatically, for example by using a Button. This is useful when the user wants to toggle between certain positions.

**Lit** — `split-layout-toggle.ts`

```typescript
@state()
private sidebarCollapsed = false;

protected override render() {
  const sidebarWidthPercentage = this.sidebarCollapsed ? 13 : 40;

  return html`
    <vaadin-split-layout style="max-height: 280px;">
      <div style="overflow: hidden; width: ${sidebarWidthPercentage}%">
        <vaadin-button
          theme="icon tertiary"
          aria-label="Expand/collapse sidebar"
          @click="${this.toggleSidebar}"
          style="float: right;"
        >
          <vaadin-icon
            icon="${this.sidebarCollapsed ? 'vaadin:arrow-right' : 'vaadin:arrow-left'}"
          ></vaadin-icon>
        </vaadin-button>
        <master-content style="clear: right"></master-content>
      </div>
      <detail-content style="width: ${100 - sidebarWidthPercentage}%"></detail-content>
    </vaadin-split-layout>
  `;
}

toggleSidebar() {
  this.sidebarCollapsed = !this.sidebarCollapsed;
}
```

**Flow** — `SplitLayoutToggle.java`

```java
button = new Button();
leftArrowIcon = VaadinIcon.ARROW_LEFT.create();
rightArrowIcon = VaadinIcon.ARROW_RIGHT.create();
Div masterContainer = new Div();
DetailContent detailContent = new DetailContent();
MasterContent masterContent = new MasterContent();
masterContent.getStyle().set("clear", "right");

sidebarCollapsed = false;

button.addClickListener(event -> {
    sidebarCollapsed = !sidebarCollapsed;
    updateSidebar();
});
button.setAriaLabel("Expand/collapse sidebar");
button.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
button.getStyle().set("float", "right");

masterContainer.add(button, masterContent);
masterContainer.getStyle().set("overflow", "hidden");

splitLayout = new SplitLayout(masterContainer, detailContent);

updateSidebar();

...

private void updateSidebar() {
    button.setIcon(sidebarCollapsed ? rightArrowIcon : leftArrowIcon);
    splitLayout.setSplitterPosition(sidebarCollapsed ? 13 : 40);
}
```

**React** — `split-layout-toggle.tsx`

```tsx
const sidebarCollapsed = useSignal(false);

const toggleSidebar = () => {
  sidebarCollapsed.value = !sidebarCollapsed.value;
};

const sidebarWidthPercentage = sidebarCollapsed.value ? 13 : 40;

return (
  <SplitLayout style={{ maxHeight: '280px' }}>
    <div
      style={{
        overflow: 'hidden',
        width: `${sidebarWidthPercentage}%`,
        display: 'flex',
        flexDirection: 'column',
      }}
    >
      <Button
        theme="icon tertiary"
        aria-label="Expand/collapse sidebar"
        onClick={toggleSidebar}
        style={{ alignSelf: 'flex-end' }}
      >
        <Icon icon={sidebarCollapsed.value ? 'vaadin:arrow-right' : 'vaadin:arrow-left'} />
      </Button>
      <MasterContent style={{ clear: 'right' }} />
    </div>

    <div style={{ width: `${100 - sidebarWidthPercentage}%` }}>
      <DetailContent />
    </div>
  </SplitLayout>
);
```

## <a id="accessibility"></a>Accessibility (since V25.3)

The split handle can be focused and operated with the keyboard, allowing users to resize the content areas without a pointing device. Clicking the handle moves focus to it, while dragging it leaves focus unchanged so as not to interrupt pointer interaction.

When the handle has focus, it can be moved with the following keys:

| Shortcut         | Function                                           |
| ---------------- | -------------------------------------------------- |
| `Right` / `Down` | Grows the primary content area by a small step.    |
| `Left` / `Up`    | Shrinks the primary content area by a small step.  |
| `Page Down`      | Grows the primary content area by a larger step.   |
| `Page Up`        | Shrinks the primary content area by a larger step. |
| `Home`           | Collapses the primary content area.                |
| `End`            | Collapses the secondary content area.              |

The arrow key directions are reversed automatically for right-to-left languages.

The handle has a default accessible name, `Resize separator`, which can be customized:

```java
SplitLayout layout = new SplitLayout();

SplitLayoutI18n i18n = new SplitLayoutI18n()
        .setSeparator("Resize separator");
layout.setI18n(i18n);
```

```html
<vaadin-split-layout .i18n="${{ separator: 'Resize separator' }}"></vaadin-split-layout>
```

```tsx
<SplitLayout i18n={{ separator: 'Resize separator' }} />
```

## <a id="best-practices"></a>Best Practices

- Don’t use Split Layout when either content area has, or should have, a fixed size.

- Split Layouts can be difficult to use in responsive applications, due to the splitter position being percentage-based, so that the content scales with the viewport.

- Use Split Layout to give the user the ability to adjust the layout. However, if only specific positions, such as collapsed and expanded, are useful to the user, use a toggle button instead. Non-adjustable layouts should use Ordered Layouts or Flex Layout.

`54c71610-9696-11ee-b9d1-0242ac120002`
