Skip to content

Layout

Layout is the frame of a page: LayoutHeader, LayoutContent and LayoutFooter stack in a column, and with hasSider a LayoutSider sits beside the content. Each part renders its landmark by default (header, aside, main, footer); change it with as.

There are two ways to scroll:

  • The page scrolls (position="static", the default). The layout grows with its content and never clips, so position="sticky" headers and siders stick to the window. Use it for documents and docs sites.
  • The panes scroll (position="absolute"). The layout fills its positioned parent, and the content, each sider and any nested layout scroll on their own. Use it for app shells.

Demos

Basic

A header, content and footer in a column; hasSider puts a sider beside them. bordered draws a rule on the side that faces the content.

App shell

position="absolute" fills the nearest positioned parent. Give that parent a height (here a 360px box; for a whole app, the window). The header and footer keep their height and the panes between them scroll.

Scrollbar

A sider, and the content of an absolute layout, scroll in a ScrollArea. Pass it props with scrollAreaProps, here trigger: "none" to always show the scrollbars, and pad the content through its contentClassName so the padding scrolls too. nativeScrollbar uses the browser’s scrollbar instead.

Collapse

showTrigger adds a toggle on the sider’s edge. collapseMode="width" narrows the content to collapsedWidth; the default transform keeps the content’s width and slides it under the edge.

Right sider, controlled

A sider after the content with placement="right" borders and toggles on its left. showTrigger="bar" draws a bar beside it. Control it with collapsed and onUpdateCollapsed; collapsedWidth={0} with showCollapsedContent={false} hides it completely.

Docs site

The page scrolls (the frame stands in for the window). The header is sticky; both siders are sticky 48px below it, as tall as the window minus that offset, and scroll on their own when their links don’t fit. hideBelow hides a sider when the window is narrower than a Grid breakpoint: the page list below m, the outline below l.

Layout Props

NameTypeDefaultDescriptionVersion
asdiv | header | footer | aside | main | nav | section | articledivThe element to render.Unreleased
hasSiderbooleanfalseLays the children out in a row. Set it when a LayoutSider is inside.Unreleased
positionstatic | absolutestaticstatic flows with the page; absolute fills the positioned parent and lets the panes scroll. Nested layouts inherit absolute’s scrolling.Unreleased

LayoutHeader, LayoutFooter Props

NameTypeDefaultDescriptionVersion
asLayoutElementheader / footerThe element to render.Unreleased
borderedbooleanfalseDraws a rule on the side that faces the content.Unreleased
positionstatic | stickystaticsticky keeps it at the top (header) or bottom (footer) while the page scrolls.Unreleased
stickyOffsetnumber | string0Distance from the edge it sticks to; numbers are px.Unreleased

LayoutContent Props

NameTypeDefaultDescriptionVersion
asLayoutElementmainThe element to render.Unreleased
nativeScrollbarbooleanfalseScroll with the browser’s scrollbar instead of a ScrollArea.Unreleased
onScroll(event) => voidundefinedCalled when the scrolling element scrolls.Unreleased
scrollAreaPropsLayoutScrollAreaPropsundefinedProps for the ScrollArea.Unreleased
scrollRefRef<HTMLElement>undefinedThe scrolling element (the content itself, or its ScrollArea), for scrollTo.Unreleased

LayoutSider Props

NameTypeDefaultDescriptionVersion
asLayoutElementasideThe element to render.Unreleased
borderedbooleanfalseDraws a rule on the side that faces the content.Unreleased
collapsedbooleanundefinedCollapsed (controlled).Unreleased
collapsedWidthnumber | string48Width when collapsed; numbers are px.Unreleased
collapseModewidth | transformtransformwidth narrows the content; transform keeps its width and slides it out.Unreleased
contentClassNamestringundefinedClass of the element that wraps the children.Unreleased
contentStyleCSSPropertiesundefinedStyle of the element that wraps the children.Unreleased
defaultCollapsedbooleanfalseCollapsed at first (uncontrolled).Unreleased
hideBelows | m | l | xlundefinedHides the sider when the window is narrower than the breakpoint (640, 1024, 1280, 1536px).Unreleased
nativeScrollbarbooleanfalseScroll with the browser’s scrollbar instead of a ScrollArea.Unreleased
onScroll(event) => voidundefinedCalled when the scrolling element scrolls.Unreleased
onUpdateCollapsed(collapsed: boolean) => voidundefinedCalled with the new state when the trigger is pressed.Unreleased
placementleft | rightleftWhich side of the content it sits on; the border and trigger face the content. Put a right sider after the content.Unreleased
positionstatic | stickystaticsticky keeps it in view while the page scrolls. Ignored inside an absolute layout, where it scrolls anyway.Unreleased
scrollAreaPropsLayoutScrollAreaPropsundefinedProps for the ScrollArea.Unreleased
scrollRefRef<HTMLElement>undefinedThe scrolling element, for scrollTo.Unreleased
showCollapsedContentbooleantrueKeeps the content visible while collapsed.Unreleased
showTriggerboolean | button | barfalseShows a collapse toggle: a button on the edge (true, button) or a bar beside it.Unreleased
stickyOffsetnumber | string0Distance from the top it sticks to; numbers are px.Unreleased
triggerLabelstringlocale’s “Toggle sidebar”Accessible name of the trigger.Unreleased
widthnumber | string272Width when expanded; numbers are px.Unreleased

Every part forwards native attributes and ref to its root element.

Notes

  • Header, footer and siders never use position: absolute. In an app shell they are flex items and the panes scroll; in a page they can be sticky.
  • Layout itself does not scroll: the content or a sider scrolls, and scrollRef / onScroll reach it. A nested Layout inside an absolute one still scrolls natively when its own children overflow.
  • The side of a sider is set on LayoutSider with placement, so one layout can have a sider on each side.
  • Themes decide the colors. To act when a sider finishes opening or closing, listen for transitionend on the sider.