Panes

Panes

Material 3 canonical layouts, from the HTML.

A .panes (or .pane-layout, or .list-detail) is the container. Two or three .pane children are the surfaces. There is no JavaScript — the HTML is the layout.

Tokens follow the M3 canonical layouts. Coplanar is the default: full-bleed surfaces and a 1dp outline-variant divider. The split is 840px, from either the viewport or the panes container itself (container-type: inline-size). Below that, one pane at a time. Compact windows add 16dp inline margins; every wider layout uses 24dp margins and 24dp spacers. Give the container a height — it is height: 100%.

Semantic child names are aliases of .pane: .list-pane, .detail-pane, .primary-pane, .supporting-pane. Mark the visible pane on compact windows with active. Optional content that should overlay the page is a side sheet, not a pane.

List-detail

The default. A 360dp list pane beside a flexible detail pane. People pick a row; the detail shows that item. Use .list-detail or a plain .panes. Pair the list pane with a list.

<div class="list-detail">
  <section class="list-pane">
    <header>
      <h2>Inbox</h2>
    </header>
    <ul class="list">…</ul>
  </section>
  <section class="detail-pane">
    <header>
      <h2>Subject</h2>
    </header>
    <div>…</div>
  </section>
</div>

Compact

On Compact windows (below 600px), the layout has 16dp inline margins. Medium, Expanded, Large, and Extra-large windows use 24dp inline margins and 24dp spacers. On Compact and Medium windows (below 840px), every pane is hidden except active. If none is active, the first pane shows. Toggle active yourself when the user picks a row or taps back — AutoInit() does not start panes. On Expanded windows both panes are shown regardless of active, so the same markup works at every size.

The illustration below is forced to one pane so the swap is visible here. Narrow the window below 840px to see the component do it itself — the list-detail demo above is the live compact view.

list.querySelectorAll('a').forEach((row) => {
  row.addEventListener('click', (event) => {
    event.preventDefault();
    detailPane.classList.add('active');
    listPane.classList.remove('active');
  });
});

back.addEventListener('click', () => {
  detailPane.classList.remove('active');
  listPane.classList.add('active');
});

Supporting pane

A flexible primary pane plus a 360dp supporting pane on the trailing edge. Use it when the extra content is secondary — a related list, inspector, or outline — and should stay in view beside the focus. Add supporting, or use .supporting-pane-layout.

start (or left) docks the supporting pane on the leading edge instead.

Article

The primary pane holds the focus of the screen. Supporting content sits beside it on expanded windows and hides on compact ones until you mark it active.

A supporting pane is in the page flow. A side sheet overlays the page and can be dismissed.

Contents

<div class="panes supporting">
  <section class="primary-pane">…</section>
  <section class="supporting-pane">…</section>
</div>

<div class="panes supporting start">…</div>

Equal

equal splits two panes 1fr / 1fr. Use it when the two surfaces have the same weight — two documents, a diff, an editor and a preview.

Draft

Write in this pane. Both columns grow equally once the window is at least 840px wide.

Preview

The preview stays in lockstep with the draft. Neither pane is the list; neither is supporting.

<div class="panes equal">
  <section class="pane">…</section>
  <section class="pane">…</section>
</div>

Three-pane

three-pane is list + focus + supporting. It needs 1200px: 360dp list, a flexible middle, 360dp supporting. Between 840px and 1200px the default two-column list-detail grid still applies, so the third pane wraps. Below 840px it is the same single-pane active pattern as the others.

Mail

Brunch this weekend?

I will be in your neighborhood doing errands this weekend. Want to grab brunch on Saturday?

Details

  • Ali Connors

    From

  • Sat, 10:00

    When

<div class="panes three-pane">
  <section class="list-pane">…</section>
  <section class="detail-pane">…</section>
  <section class="supporting-pane">…</section>
</div>

Appearance

Coplanar is the default: the panes share one surface, with a 1dp divider on expanded windows. separated (or floating) insets the panes 24dp, rounds them to 16dp, and fills each with surface-container-low.

On a separated pane, elevated adds elevation 1. outlined switches the fill to surface and draws a 1dp outline.

Outlined

Surface, 1dp outline-variant stroke, no elevation.

Elevated

Surface-container-low at elevation 1.

<div class="panes equal separated">
  <section class="pane outlined">…</section>
  <section class="pane elevated">…</section>
</div>

A pane

Each pane is a column. A child <header> (or .pane-header) is the 64dp top bar: icon-only buttons, then a title-large heading. A child <main>, .pane-content, .pane-body, or <div> is the scrolling body. A last-child <footer>, .pane-footer, or <nav> is the 56dp action bar.

A direct .list fills the pane with no extra padding, so list rows can run edge to edge under the header.

<section class="pane">
  <header>
    <button type="button" aria-label="Back">
      <span class="material-symbols" aria-hidden="true">arrow_back</span>
    </button>
    <h2>Headline</h2>
    <button type="button" aria-label="More">
      <span class="material-symbols" aria-hidden="true">more_vert</span>
    </button>
  </header>
  <div>…</div>
  <footer>
    <button type="button" class="text">Action</button>
  </footer>
</section>

Tokens

Token Default
--md-comp-pane-margin 16px Compact; 24px Medium and wider
--md-comp-pane-gap24px
--md-comp-pane-divider-coloroutline-variant
--md-comp-pane-container-colorsurface
--md-comp-pane-container-shape0px (16px separated)
--md-comp-pane-list-width360px
--md-comp-pane-supporting-width360px
  • Source color

    The seed every generated ramp derives from. Pick one and browse the docs — the whole theme follows. Error does not: it is a fixed hue.