Skip to main content brightness_auto motion_photos_off palette download more_vert
toc

Scaffold

A scaffold arranges the bars, rails and panes around an app's content, and adapts them to the window size.

Inbox inbox Inbox send Sent inbox Inbox send Sent

Your messages appear here.

<md-gb-app-scaffold style="inline-size: 100%; block-size: 360px">
  <md-gb-app-bar slot="top-app-bar">Inbox</md-gb-app-bar>
  <md-gb-nav-bar slot="navigation-bar" aria-label="Primary">
    <md-gb-nav-bar-item active>
      <md-gb-icon slot="icon">inbox</md-gb-icon>
      Inbox
    </md-gb-nav-bar-item>
    <md-gb-nav-bar-item>
      <md-gb-icon slot="icon">send</md-gb-icon>
      Sent
    </md-gb-nav-bar-item>
  </md-gb-nav-bar>
  <md-gb-nav-rail slot="navigation-rail" aria-label="Primary">
    <md-gb-nav-rail-item selected>
      <md-gb-icon slot="icon">inbox</md-gb-icon>
      Inbox
    </md-gb-nav-rail-item>
    <md-gb-nav-rail-item>
      <md-gb-icon slot="icon">send</md-gb-icon>
      Sent
    </md-gb-nav-rail-item>
  </md-gb-nav-rail>
  <p>Your messages appear here.</p>
</md-gb-app-scaffold>
  • Structure the app in bars, rails and panes. Bars frame the page, rails run along its edges, and panes hold the content.
  • Provide both navigation components. Give the scaffold a navigation bar and a navigation rail with the same destinations. It shows the bar in compact windows and the rail from medium windows up, and you keep their selection in sync.
  • Pick the pane layout by content. Use list-detail for a collection and its details, supporting pane for a focus area with related content, and feed for a grid of items.
  • Use one to three panes. The number of visible panes follows the window size.

This component is new in M3 Expressive.

md-gb-app-scaffold places bars and rails around its content. md-gb-pane-scaffold goes in the content and arranges the panes.

<md-gb-app-scaffold style="inline-size: 100%; block-size: 360px">
  <md-gb-app-bar slot="top-app-bar">Notes</md-gb-app-bar>
  <md-gb-nav-bar slot="navigation-bar" aria-label="Primary">
    <md-gb-nav-bar-item active>
      <md-gb-icon slot="icon">notes</md-gb-icon>
      Notes
    </md-gb-nav-bar-item>
    <md-gb-nav-bar-item>
      <md-gb-icon slot="icon">archive</md-gb-icon>
      Archive
    </md-gb-nav-bar-item>
  </md-gb-nav-bar>
  <md-gb-nav-rail slot="navigation-rail" aria-label="Primary">
    <md-gb-nav-rail-item selected>
      <md-gb-icon slot="icon">notes</md-gb-icon>
      Notes
    </md-gb-nav-rail-item>
    <md-gb-nav-rail-item>
      <md-gb-icon slot="icon">archive</md-gb-icon>
      Archive
    </md-gb-nav-rail-item>
  </md-gb-nav-rail>
  <md-gb-fab slot="fab" aria-label="New note">
    <md-gb-icon>add</md-gb-icon>
  </md-gb-fab>
  <md-gb-pane-scaffold>
    <md-gb-list slot="secondary" aria-label="Notes">
      <md-gb-list-item>Groceries</md-gb-list-item>
      <md-gb-list-item>Trip ideas</md-gb-list-item>
    </md-gb-list>
    <article>
      <h2>Groceries</h2>
      <p>Milk, eggs and bread.</p>
    </article>
    <p slot="placeholder">Select a note</p>
  </md-gb-pane-scaffold>
</md-gb-app-scaffold>

The default layout shows a list in the secondary slot and its detail in the default slot. In windows with one pane they take turns: call openDetail() when someone picks an item and closeDetail() from a back button. The placeholder slot fills the detail pane until one is open.

<md-gb-pane-scaffold style="inline-size: 100%; block-size: 240px">
  <md-gb-list slot="secondary" aria-label="Conversations">
    <md-gb-list-item>Ali Connors</md-gb-list-item>
    <md-gb-list-item>Sandra Adams</md-gb-list-item>
    <md-gb-list-item>Trevor Hansen</md-gb-list-item>
  </md-gb-list>
  <article>
    <h2>Brunch this weekend?</h2>
    <p>From Ali Connors</p>
  </article>
  <p slot="placeholder">Select a conversation</p>
</md-gb-pane-scaffold>

Set layout="supporting-pane" for a focus area in the default slot with related content in the secondary slot, at the trailing side by default.

<md-gb-pane-scaffold layout="supporting-pane" style="inline-size: 100%; block-size: 360px">
  <article>
    <h2>Quarterly plan</h2>
    <p>The goals and milestones for the next three months.</p>
  </article>
  <aside slot="secondary">
    <h3>Related notes</h3>
    <p>Budget review</p>
  </aside>
</md-gb-pane-scaffold>

Set layout="feed" to lay the default slot's items out on a grid, with an optional secondary pane beside it.

Lemon pasta Sourdough Pad thai Summer salad
<md-gb-pane-scaffold layout="feed" style="inline-size: 100%; block-size: 240px">
  <md-gb-card>Lemon pasta</md-gb-card>
  <md-gb-card>Sourdough</md-gb-card>
  <md-gb-card>Pad thai</md-gb-card>
  <md-gb-card>Summer salad</md-gb-card>
</md-gb-pane-scaffold>

Add resizable to a two-pane layout to show a drag handle between the panes. pane-width sets the width of the secondary pane in pixels, and collapsed-pane records a pane collapsed with the handle. The scaffold fires pane-resize when the panes change size.

<md-gb-pane-scaffold resizable pane-width="240" style="inline-size: 100%; block-size: 240px">
  <md-gb-list slot="secondary" aria-label="Folders">
    <md-gb-list-item>Inbox</md-gb-list-item>
    <md-gb-list-item>Drafts</md-gb-list-item>
  </md-gb-list>
  <article>
    <h2>Inbox</h2>
    <p>Drag the handle to resize the list.</p>
  </article>
</md-gb-pane-scaffold>

When there is no room for a supporting pane beside the content, set levitate to floating or docked to lift the secondary pane above it instead of stacking it below. A docked pane sits at the bottom edge on compact windows, like a bottom sheet. Open it with openLevitated() and close it with closeLevitated(). Add levitate-modal for a scrim, and levitate-label to name the pane.

HTMLCSSTS
<md-gb-button id="comments-button">Comments</md-gb-button>
<md-gb-pane-scaffold layout="supporting-pane" levitate="floating" levitate-label="Comments">
  <article>
    <h2>Quarterly plan</h2>
    <p>The goals and milestones for the next three months.</p>
  </article>
  <aside slot="secondary">
    <h3>Comments</h3>
    <p>Looks good to me.</p>
  </aside>
</md-gb-pane-scaffold>
  • Give each navigation component an aria-label, such as "Primary navigation", and keep the bar and rail selections in sync.
  • In a single-pane list-detail layout, provide a back button that calls closeDetail().
  • A modal levitated pane takes focus, closes with Escape and when someone uses the content behind it, and is named by levitate-label.
  • A floating pane's move and resize handles also work with the arrow keys. Use drag-handle-label, levitate-move-label and levitate-resize-label to translate their names.

A Material Design app scaffold (bars, rails, FAB, snackbar).

Property Attribute Type Default
autoExpandRail
Whether to expand a slotted navigation rail at large and extra-large windows and collapse it below (spec: breakpoints, swapping components). Applied when the window size class changes.
auto-expand-rail boolean false
navigation
Which navigation component to show.
navigation ScaffoldNavigation 'auto'
sideSheetNavigation
What the navigation rail does while a side sheet is present (spec: breakpoints and scaffold): keep it as is, collapse it to the collapsed rail, or hide it completely. A side sheet is present while the nested pane scaffold shows its tertiary pane or side-sheet-open is set.
side-sheet-navigation SideSheetNavigation 'keep'
sideSheetOpen
Whether an app-managed side sheet is open.
side-sheet-open boolean false
Slot Description
default The content, typically an md-gb-pane-scaffold. Scrolls.
companion-rail A companion rail on the trailing side of large and extra-large windows, holding supporting controls or actions that modify or relate to the content in a pane.
fab A FAB, 16px from the trailing and bottom edges of the content.
navigation-bar A navigation bar (md-gb-nav-bar) at the bottom.
navigation-rail A navigation rail (md-gb-nav-rail) at the leading edge.
snackbar A snackbar host (md-gb-snackbar), above the FAB.
toolbar A toolbar floating in the bottom rail region, centered above the navigation bar (mobile).
top-app-bar A top app bar (md-gb-app-bar), beside the rail.
Event Description
navigation-change
CustomEvent<NavigationChangeDetail>
Fired when the shown navigation component changes.
window-class-change
CustomEvent<WindowClassChangeDetail>
Fired when the window size class changes.
window-height-class-change
CustomEvent<WindowHeightClassChangeDetail>
Fired when the window height size class changes.
Part Description
::part(body) The content region (content, FAB and snackbar).
::part(companion-rail) The companion rail region.
::part(content) The scrolling content container.
::part(navigation-bar) The navigation bar region.
::part(rail) The navigation rail region.
::part(scaffold) The scaffold grid.
::part(toolbar) The floating toolbar region.
::part(top-app-bar) The top app bar region.
Property Description
--container-color Scaffold background.
--content-color Scaffold content color.
--scrollbar-gutter stable reserves the content's scrollbar gutter, so a scrollbar that appears doesn't move the content (default auto: the pane widths are measured to the edges).

A Material Design pane scaffold (list-detail, supporting pane, feed).

Property Attribute Type Default
arrangement
How two panes share the width.
arrangement PaneArrangement 'fixed-flexible'
collapsedPane
A pane collapsed with the drag handle, or null.
collapsed-pane "primary" "secondary"
detailOpen
List-detail: whether an item is selected. Single-pane windows show the detail (primary) pane when true and the list (secondary) pane when false; two-pane windows show the placeholder slot instead of the detail while false.
detail-open boolean false
dragHandleLabel
Accessible label of the drag handle.
drag-handle-label string 'Resize panes'
handleTap
What a tap, Enter or Space on the drag handle does, the single-pointer alternative to dragging it: toggle (default) switches between one and two panes; cycle steps through the snap widths and then collapses the secondary pane.
handle-tap PaneHandleTap 'toggle'
layout
The canonical layout.
layout PaneScaffoldLayout 'list-detail'
levitate
The levitate strategy for the secondary pane of supporting pane and feed layouts in windows too small for two panes: none reflows it below the primary pane, floating floats it above, docked docks it to the bottom edge at compact (floating from medium).
levitate PaneLevitate 'none'
levitateCoplanar
Keeps a levitated pane co-planar at large and extra-large windows. By default it floats there (spec: scaffold, "On large screens: floating panes are the default").
levitate-coplanar boolean false
levitateDraggable
Lets a floating pane be dragged by its handle, or moved with the arrow keys while the handle is focused (spec: scaffold, floating panes "can be customized to be dragged or resized").
levitate-draggable boolean false
levitateLabel
Accessible label of a modal levitated pane (its dialog role).
levitate-label string ''
levitateModal
Whether the levitated secondary pane is modal (scrim, inert panes).
levitate-modal boolean false
levitateMoveLabel
Accessible label of the floating pane's move handle.
levitate-move-label string 'Move pane'
levitateOpen
Whether the levitated secondary pane is shown.
levitate-open boolean false
levitateResizable
Lets a floating pane be resized by its corner handle, or with the arrow keys while the handle is focused.
levitate-resizable boolean false
levitateResizeLabel
Accessible label of the floating pane's resize handle.
levitate-resize-label string 'Resize pane'
mediumTwoPane
Whether medium windows show two panes (50% each) instead of one. The spec limits this to low-density content such as settings.
medium-two-pane boolean false
paneWidth
Width in px of the secondary pane set with the drag handle, or null for the default width. Set it to restore a persisted width.
pane-width number null
resizable
Whether two-pane layouts render a drag handle to resize the panes.
resizable boolean false
resizeBehavior
persistent keeps a resized width or collapsed pane across window size class changes; temporary returns to the default layout. Defaults to persistent for list-detail and temporary for the other layouts.
resize-behavior PaneResizeBehavior undefined
scrollLabel
Accessible label of the stacked panes' scroll region. Only used while the stacked panes overflow and hold nothing focusable: the region is then focusable (so the keyboard can scroll it) and a labelled region.
scroll-label string 'Panes'
secondaryPosition
Where the secondary pane sits in two-pane layouts. Defaults to start for list-detail and end for supporting pane and feed layouts. Mirrors in right-to-left.
secondary-position PanePosition undefined
Slot Description
default The primary (flexible) pane: the detail pane of a list-detail layout, the focus pane of a supporting pane layout, or the feed items (laid out on a grid) of a feed layout.
placeholder Shown in the primary pane of a two-pane list-detail layout while detail-open is false (no item selected). Levitate (spec: scaffold, "Levitate"): with levitate="floating" or levitate="docked", the secondary pane of a supporting pane or feed layout floats above the primary pane (or docks to the bottom edge at compact, like a bottom sheet) in windows too small for two co-planar panes, while levitate-open is set. levitate-modal makes it modal: a scrim covers the panes, the primary pane is inert, focus moves into the pane and back to the trigger, and the pane closes when something behind it is used or Escape is pressed. Modality is scoped to the scaffold; use md-gb-dialog or md-gb-sheet for app-wide modals. At large and extra-large windows a levitated pane keeps floating (spec: "On large screens, floating panes are the default"); the scrim is optional (levitate-modal adds it). levitate-coplanar opts into a co-planar pane there instead. levitate-draggable and levitate-resizable add a move handle and a resize corner to a floating pane: drag them, or focus them and use the arrow keys (Shift moves in larger steps). levitate-change fires after each move or resize. Foldables: the scaffold reads the fold (hinge) from the Viewport Segments API and keeps panes off it. A vertical fold splits two panes at the fold with the spacer on it (at least the spacer width); a horizontal fold (tabletop) stacks the supporting pane below it. The fold crossing the scaffold is reflected as the fold attribute (vertical or horizontal). Browsers without the API keep the regular layout.
secondary The secondary pane: the list of a list-detail layout or the supporting pane. It is the fixed pane in fixed-and-flexible arrangements.
tertiary An optional third pane (e.g. a standard side sheet), shown at extra-large only.
Event Description
levitate-close
Event
Fired when the scaffold closes a levitated pane (Escape, or using something behind a modal pane).
pane-layout-change
CustomEvent<PaneLayoutChangeDetail>
Fired when the visible panes change.
pane-resize
CustomEvent<PaneResizeDetail>
Fired when the panes are resized or collapsed with the drag handle.
window-class-change
CustomEvent<WindowClassChangeDetail>
Fired when the window size class changes.
window-height-class-change
CustomEvent<WindowHeightClassChangeDetail>
Fired when the window height size class changes.
Method Description
closeDetail
() => void
List-detail: returns to the list (e.g. from the detail pane's back button in a single-pane window).
closeLevitated
() => void
Hides the levitated secondary pane.
measureFold
() => void
Finds where the viewport's fold crosses the scaffold. Call it after moving the scaffold without resizing it.
openDetail
() => void
List-detail: shows the detail pane (e.g. after selecting an item).
openLevitated
() => void
Shows the levitated secondary pane.
resetPaneWidth
() => void
Returns the panes to their default widths.
Part Description
::part(drag-handle) The drag handle.
::part(pane) Each pane.
::part(primary) The primary pane.
::part(scaffold) The flex container of the panes.
::part(scrim) The scrim behind a modal levitated pane.
::part(secondary) The secondary pane.
::part(spacer) The spacer between panes.
::part(tertiary) The tertiary pane.
Property Description
--feed-columns Overrides the number of feed grid columns.
--md-gb-scaffold-companion-inline-size Width of a companion rail on the trailing side of the scaffold. Set by md-gb-app-scaffold.
--md-gb-scaffold-nav-inline-size Width of a navigation rail beside the scaffold, so split panes keep the spacer centered in the window. Set by md-gb-app-scaffold.
--pane-container-color Pane background (transparent: panes blend with the background, implicit grouping).
--pane-container-shape Pane corner radius.
--scrollbar-gutter stable reserves the panes' scrollbar gutters, so a scrollbar that appears doesn't move their content (default auto: the spacer is centered on the pane edges).
Install Material Web 3.0

Your browser did not offer to install the docs as an app. Install them from the browser instead:

Close
Send feedback
Bug Documentation Idea

Opens a new GitHub issue for material-components/material-web in a new tab, with this filled in.

Cancel Open issue