SplitView


Use the SplitView component to build draggable two-pane layouts with Bulma semantic divider colors, horizontal or vertical orientation, nested workspaces, disabled states, and resize events.

API Documentation

How it works #

The SplitView component creates a two-pane workspace with a draggable divider so users can decide how much room each side should receive.

How to use:
  1. Place the component inside a container with an explicit height.
  2. Provide the two pane fragments through <Pane1> and <Pane2>.
  3. Optionally set PrimaryPaneSize to choose the initial split percentage.
  4. Optionally set Color to a Bulma semantic value when the divider should pick up your UI accent color.
  5. Drag the divider with a mouse or touch input, depending on the device.
This demo shows a common master-detail workspace with a resizable file list and preview area.

Project Explorer

  • Components
  • Pages
  • Services
  • wwwroot
  • Program.cs

File Preview

SplitView works well when the left pane lists items and the right pane shows details, previews, or editors for the current selection.

Drag the divider to decide whether navigation or the working surface should receive more space.

<div style="height: 22rem;">
    <SplitView PrimaryPaneSize="32">
        <Pane1>
            <div style="padding: 1rem;">
                <p class="title is-6 mb-3">Project Explorer</p>
                <div class="content">
                    <ul>
                        <li>Components</li>
                        <li>Pages</li>
                        <li>Services</li>
                        <li>wwwroot</li>
                        <li>Program.cs</li>
                    </ul>
                </div>
            </div>
        </Pane1>
        <Pane2>
            <div style="padding: 1rem;">
                <p class="title is-6 mb-3">File Preview</p>
                <div class="box mb-3">
                    SplitView works well when the left pane lists items and the right pane shows details, previews, or editors for the current selection.
                </div>
                <div class="content">
                    <p>Drag the divider to decide whether navigation or the working surface should receive more space.</p>
                </div>
            </div>
        </Pane2>
    </SplitView>
</div>

Disable #

The IsDisabled parameter freezes the current pane sizes and turns the divider into a visual boundary instead of an interactive control.

How to use:
  1. Bind IsDisabled to a boolean field.
  2. Toggle that field when your page enters or leaves a locked layout state.
  3. Optionally bind PrimaryPaneSize so the current split stays visible in your page state.
This demo lets you lock and unlock the divider while keeping the current split percentage on screen.
Current IsDisabled: False Current PrimaryPaneSize: 50%

Locked Navigation

Disable dragging when you want to preserve a known layout during a wizard, review mode, or presentation flow.

Working Surface

Turn dragging off and on with the buttons above, then try moving the divider again.
<div class="is-flex is-align-items-center is-flex-wrap-wrap mb-4" style="gap: 0.75rem;">
    <Button Color="ButtonColor.Primary" Size="ButtonSize.Small" @onclick="EnableDrag">Enable drag</Button>
    <Button Color="ButtonColor.Warning" Size="ButtonSize.Small" @onclick="DisableDrag">Disable drag</Button>
    <Button Size="ButtonSize.Small" @onclick="ToggleDrag">Toggle</Button>
    <span>Current <code>IsDisabled</code>: <strong>@isDisabled</strong></span>
    <span>Current <code>PrimaryPaneSize</code>: <strong>@primaryPaneSize.ToString("0.##")%</strong></span>
</div>

<div style="height: 20rem;">
    <SplitView IsDisabled="@isDisabled" @bind-PrimaryPaneSize="primaryPaneSize">
        <Pane1>
            <div style="padding: 1rem;">
                <p class="title is-6 mb-3">Locked Navigation</p>
                <div class="content">
                    <p>Disable dragging when you want to preserve a known layout during a wizard, review mode, or presentation flow.</p>
                </div>
            </div>
        </Pane1>
        <Pane2>
            <div style="padding: 1rem;">
                <p class="title is-6 mb-3">Working Surface</p>
                <div class="box">
                    Turn dragging off and on with the buttons above, then try moving the divider again.
                </div>
            </div>
        </Pane2>
    </SplitView>
</div>

@code {
    private bool isDisabled;
    private double primaryPaneSize = 50;

    private void DisableDrag() => isDisabled = true;

    private void EnableDrag() => isDisabled = false;

    private void ToggleDrag() => isDisabled = !isDisabled;
}

Colors #

The Color parameter applies a Bulma semantic accent to the divider, which helps the SplitView align with branded, informational, success, or destructive workflows.

How to use:
  1. Set Color to a Bulma semantic value such as Primary, Link, Success, or Danger.
  2. Use the semantic color as the divider default when you want a stronger visual cue between the panes.
  3. Optionally override individual divider states later with the explicit divider color parameters.
This demo covers the full SplitViewColor palette so you can see how the interaction states inherit each accent.

Default

Overview
Default neutral divider

Primary

Navigation
Primary divider accent

Link

Activity
Link divider accent

Info

Insights
Info divider accent

Success

Status
Success divider accent

Warning

Review
Warning divider accent

Danger

Alerts
Danger divider accent

White

Contrast
White divider accent

Light

Palette
Light divider accent

Dark

Inspector
Dark divider accent

Black

Console
Black divider accent
<div class="is-flex is-flex-direction-column" style="gap: 1rem;">
    <div>
        <p class="title is-6 mb-2">Default</p>
        <div class="box" style="height: 8rem;">
            <SplitView PrimaryPaneSize="34" Color="SplitViewColor.None">
                <Pane1>
                    <div style="padding: 1rem;">
                        <strong>Overview</strong>
                    </div>
                </Pane1>
                <Pane2>
                    <div style="padding: 1rem;">
                        <span>Default neutral divider</span>
                    </div>
                </Pane2>
            </SplitView>
        </div>
    </div>

    <div>
        <p class="title is-6 mb-2">Primary</p>
        <div class="box" style="height: 8rem;">
            <SplitView PrimaryPaneSize="34" Color="SplitViewColor.Primary">
                <Pane1>
                    <div style="padding: 1rem;">
                        <strong>Navigation</strong>
                    </div>
                </Pane1>
                <Pane2>
                    <div style="padding: 1rem;">
                        <span>Primary divider accent</span>
                    </div>
                </Pane2>
            </SplitView>
        </div>
    </div>

    <div>
        <p class="title is-6 mb-2">Link</p>
        <div class="box" style="height: 8rem;">
            <SplitView PrimaryPaneSize="34" Color="SplitViewColor.Link">
                <Pane1>
                    <div style="padding: 1rem;">
                        <strong>Activity</strong>
                    </div>
                </Pane1>
                <Pane2>
                    <div style="padding: 1rem;">
                        <span>Link divider accent</span>
                    </div>
                </Pane2>
            </SplitView>
        </div>
    </div>

    <div>
        <p class="title is-6 mb-2">Info</p>
        <div class="box" style="height: 8rem;">
            <SplitView PrimaryPaneSize="34" Color="SplitViewColor.Info">
                <Pane1>
                    <div style="padding: 1rem;">
                        <strong>Insights</strong>
                    </div>
                </Pane1>
                <Pane2>
                    <div style="padding: 1rem;">
                        <span>Info divider accent</span>
                    </div>
                </Pane2>
            </SplitView>
        </div>
    </div>

    <div>
        <p class="title is-6 mb-2">Success</p>
        <div class="box" style="height: 8rem;">
            <SplitView PrimaryPaneSize="34" Color="SplitViewColor.Success">
                <Pane1>
                    <div style="padding: 1rem;">
                        <strong>Status</strong>
                    </div>
                </Pane1>
                <Pane2>
                    <div style="padding: 1rem;">
                        <span>Success divider accent</span>
                    </div>
                </Pane2>
            </SplitView>
        </div>
    </div>

    <div>
        <p class="title is-6 mb-2">Warning</p>
        <div class="box" style="height: 8rem;">
            <SplitView PrimaryPaneSize="34" Color="SplitViewColor.Warning">
                <Pane1>
                    <div style="padding: 1rem;">
                        <strong>Review</strong>
                    </div>
                </Pane1>
                <Pane2>
                    <div style="padding: 1rem;">
                        <span>Warning divider accent</span>
                    </div>
                </Pane2>
            </SplitView>
        </div>
    </div>

    <div>
        <p class="title is-6 mb-2">Danger</p>
        <div class="box" style="height: 8rem;">
            <SplitView PrimaryPaneSize="34" Color="SplitViewColor.Danger">
                <Pane1>
                    <div style="padding: 1rem;">
                        <strong>Alerts</strong>
                    </div>
                </Pane1>
                <Pane2>
                    <div style="padding: 1rem;">
                        <span>Danger divider accent</span>
                    </div>
                </Pane2>
            </SplitView>
        </div>
    </div>

    <div>
        <p class="title is-6 mb-2">White</p>
        <div class="box has-background-dark" style="height: 8rem;">
            <SplitView PrimaryPaneSize="34" Color="SplitViewColor.White">
                <Pane1>
                    <div class="has-text-white" style="padding: 1rem;">
                        <strong>Contrast</strong>
                    </div>
                </Pane1>
                <Pane2>
                    <div class="has-text-white" style="padding: 1rem;">
                        <span>White divider accent</span>
                    </div>
                </Pane2>
            </SplitView>
        </div>
    </div>

    <div>
        <p class="title is-6 mb-2">Light</p>
        <div class="box has-background-dark" style="height: 8rem;">
            <SplitView PrimaryPaneSize="34" Color="SplitViewColor.Light">
                <Pane1>
                    <div class="has-text-white" style="padding: 1rem;">
                        <strong>Palette</strong>
                    </div>
                </Pane1>
                <Pane2>
                    <div class="has-text-white" style="padding: 1rem;">
                        <span>Light divider accent</span>
                    </div>
                </Pane2>
            </SplitView>
        </div>
    </div>

    <div>
        <p class="title is-6 mb-2">Dark</p>
        <div class="box" style="height: 8rem;">
            <SplitView PrimaryPaneSize="34" Color="SplitViewColor.Dark">
                <Pane1>
                    <div style="padding: 1rem;">
                        <strong>Inspector</strong>
                    </div>
                </Pane1>
                <Pane2>
                    <div style="padding: 1rem;">
                        <span>Dark divider accent</span>
                    </div>
                </Pane2>
            </SplitView>
        </div>
    </div>

    <div>
        <p class="title is-6 mb-2">Black</p>
        <div class="box" style="height: 8rem;">
            <SplitView PrimaryPaneSize="34" Color="SplitViewColor.Black">
                <Pane1>
                    <div style="padding: 1rem;">
                        <strong>Console</strong>
                    </div>
                </Pane1>
                <Pane2>
                    <div style="padding: 1rem;">
                        <span>Black divider accent</span>
                    </div>
                </Pane2>
            </SplitView>
        </div>
    </div>
</div>

Orientation #

The Orientation parameter switches the SplitView between a left-right workspace and a top-bottom workspace without changing the basic component shape.

How to use:
  1. Use SplitViewOrientation.Horizontal for side-by-side panes.
  2. Use SplitViewOrientation.Vertical for stacked panes.
  3. Choose the orientation that best matches the way users compare or edit the content.
This demo compares both orientations in one place so you can see how the divider and pane flow adapt.

Horizontal

Navigation

The panes sit side by side for classic master-detail layouts.

Details

Horizontal mode is a good fit for desktops and wide work areas.

Vertical

Preview

Vertical mode stacks the panes and lets the divider move up and down.

Notes

This layout works nicely for previews above supporting tools or metadata.

<div class="is-flex is-flex-direction-column" style="gap: 1rem;">
    <div>
        <p class="title is-6 mb-2">Horizontal</p>
        <div style="height: 14rem;">
            <SplitView Orientation="SplitViewOrientation.Horizontal" PrimaryPaneSize="38">
                <Pane1>
                    <div style="padding: 1rem;">
                        <p class="mb-2"><strong>Navigation</strong></p>
                        <div class="content">
                            <p>The panes sit side by side for classic master-detail layouts.</p>
                        </div>
                    </div>
                </Pane1>
                <Pane2>
                    <div style="padding: 1rem;">
                        <p class="mb-2"><strong>Details</strong></p>
                        <div class="content">
                            <p>Horizontal mode is a good fit for desktops and wide work areas.</p>
                        </div>
                    </div>
                </Pane2>
            </SplitView>
        </div>
    </div>

    <div>
        <p class="title is-6 mb-2">Vertical</p>
        <div style="height: 16rem;">
            <SplitView Orientation="SplitViewOrientation.Vertical" PrimaryPaneSize="42">
                <Pane1>
                    <div style="padding: 1rem;">
                        <p class="mb-2"><strong>Preview</strong></p>
                        <div class="content">
                            <p>Vertical mode stacks the panes and lets the divider move up and down.</p>
                        </div>
                    </div>
                </Pane1>
                <Pane2>
                    <div style="padding: 1rem;">
                        <p class="mb-2"><strong>Notes</strong></p>
                        <div class="content">
                            <p>This layout works nicely for previews above supporting tools or metadata.</p>
                        </div>
                    </div>
                </Pane2>
            </SplitView>
        </div>
    </div>
</div>

Mixed #

Multiple SplitView instances can be nested to build richer workspaces such as explorers, editors, previews, and diagnostics panels.

How to use:
  1. Place one SplitView inside the pane content of another SplitView.
  2. Give each nested area its own height by letting the parent pane fill the available space.
  3. Mix horizontal and vertical orientations to create the workspace shape you need.
This demo shows a nested layout with a left explorer, a top editor, and a bottom output panel.

Explorer

  • Dashboard
  • Reports
  • Queries
  • Settings

Editor

SELECT *
FROM Customers
WHERE IsActive = 1
ORDER BY Name;

Output

Nested SplitView layouts let you combine navigation, editing, diagnostics, and previews in a single reusable pattern.

<div style="height: 24rem;">
    <SplitView Orientation="SplitViewOrientation.Horizontal" PrimaryPaneSize="26">
        <Pane1>
            <div style="padding: 1rem;">
                <p class="title is-6 mb-3">Explorer</p>
                <div class="content">
                    <ul>
                        <li>Dashboard</li>
                        <li>Reports</li>
                        <li>Queries</li>
                        <li>Settings</li>
                    </ul>
                </div>
            </div>
        </Pane1>
        <Pane2>
            <SplitView Orientation="SplitViewOrientation.Vertical" PrimaryPaneSize="58">
                <Pane1>
                    <div style="padding: 1rem;">
                        <p class="title is-6 mb-3">Editor</p>
                        <div class="box">
                            SELECT *
                            <br />
                            FROM Customers
                            <br />
                            WHERE IsActive = 1
                            <br />
                            ORDER BY Name;
                        </div>
                    </div>
                </Pane1>
                <Pane2>
                    <div style="padding: 1rem;">
                        <p class="title is-6 mb-3">Output</p>
                        <div class="content">
                            <p>Nested SplitView layouts let you combine navigation, editing, diagnostics, and previews in a single reusable pattern.</p>
                        </div>
                    </div>
                </Pane2>
            </SplitView>
        </Pane2>
    </SplitView>
</div>

Events #

The SplitView component exposes resize lifecycle events so you can react when dragging starts, while the divider moves, and after the final size is committed.

How to use:
  1. Handle OnResizeStarted when you want to note the beginning of user interaction.
  2. Handle OnResized to update live indicators such as labels or measurements while dragging.
  3. Handle OnResizeEnded when you want to persist the final layout choice.
This demo shows live resize feedback along with a small event log for the drag lifecycle.

Current PrimaryPaneSize: 40%

Latest OnResized message: No resize yet.

Resizable Pane

Drag the divider and watch the current size plus the event messages update.

Event Summary

The move event updates the live percentage while the start and end events are recorded below.

<div class="mb-4">
    <p class="mb-2">Current <code>PrimaryPaneSize</code>: <strong>@currentPrimaryPaneSize.ToString("0.##")%</strong></p>
    <p class="mb-0">Latest <code>OnResized</code> message: <strong>@lastResizeMessage</strong></p>
</div>

<div style="height: 18rem;">
    <SplitView PrimaryPaneSize="@currentPrimaryPaneSize"
               OnResizeStarted="HandleResizeStarted"
               OnResized="HandleResized"
               OnResizeEnded="HandleResizeEnded">
        <Pane1>
            <div style="padding: 1rem;">
                <p class="title is-6 mb-3">Resizable Pane</p>
                <div class="content">
                    <p>Drag the divider and watch the current size plus the event messages update.</p>
                </div>
            </div>
        </Pane1>
        <Pane2>
            <div style="padding: 1rem;">
                <p class="title is-6 mb-3">Event Summary</p>
                <div class="content">
                    <p>The move event updates the live percentage while the start and end events are recorded below.</p>
                </div>
            </div>
        </Pane2>
    </SplitView>
</div>

<div class="mt-5" style="max-height: 180px; overflow-y: auto;">
    @foreach (var item in messages)
    {
        <p>Event: @item.Event, Message: @item.Message, UTC Time: @item.TimeStamp</p>
    }
</div>

@code {
    private double currentPrimaryPaneSize = 40;
    private string lastResizeMessage = "No resize yet.";
    private List<SplitViewMessage> messages = new();

    private void HandleResized(SplitViewResizeEventArgs args)
    {
        currentPrimaryPaneSize = args.PrimaryPaneSize;
        lastResizeMessage = $"Pane 1: {args.PrimaryPaneSize:0.##}%, Pane 2: {args.SecondaryPaneSize:0.##}%";
    }

    private void HandleResizeEnded(SplitViewResizeEventArgs args) =>
        messages.Add(new("OnResizeEnded", $"Pane 1: {args.PrimaryPaneSize:0.##}%, Pane 2: {args.SecondaryPaneSize:0.##}%", DateTime.UtcNow));

    private void HandleResizeStarted(SplitViewResizeEventArgs args) =>
        messages.Add(new("OnResizeStarted", $"Pane 1: {args.PrimaryPaneSize:0.##}%, Pane 2: {args.SecondaryPaneSize:0.##}%", DateTime.UtcNow));

    private record SplitViewMessage(string Event, string Message, DateTime TimeStamp);
}
DO YOU KNOW?
This demo website is built using the BlazorExpress.Bulma library and published on the Azure Web App. See our source code on GitHub.