PageLayout
PageLayout defines the header, main, pane, and footer areas of a page.
Page navigation navigation
React examples
We recommend looking at the PageLayout Storybook stories to see it in a more realistic context.
The PageLayout component is intended for full PageLayouts, so many of the layout adjustments wouldn't be visible in the example boxes.
To ensure a sidebar spans the full page height, the parent element must always fill the viewport, even when content is shorter than the screen.
Default
Dividers between areas
Custom padding between areas
Custom padding around layout
This example removes the padding around the PageLayout.
Custom column and row gap
This example removes the gaps between each part of the PageLayout.
Custom pane width
You can pick from one of the provided width keys or set rbitrary widths by passing a CSS width as a string. See the PageLayout.Pane props in the props section below for more information.
This example configures the pane width as follows:
- default of
'80px' - minimum of
'40px' - maximum of
'100px'
With a resizable pane
With a sticky pane
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam at enim id lorem tempus egestas a non ipsum. Maecenas imperdiet ante quam, at varius lorem molestie vel. Sed at eros consequat, varius tellus et, auctor felis. Donec pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec sit amet massa purus. Nunc sem lectus, bibendum a sapien nec, tristique tempus felis. Ut porttitor auctor tellus in imperdiet. Ut blandit tincidunt augue, quis fringilla nunc tincidunt sed. Vestibulum auctor euismod nisi. Nullam tincidunt est in mi tincidunt dictum. Sed consectetur aliquet velit ut ornare.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam at enim id lorem tempus egestas a non ipsum. Maecenas imperdiet ante quam, at varius lorem molestie vel. Sed at eros consequat, varius tellus et, auctor felis. Donec pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec sit amet massa purus. Nunc sem lectus, bibendum a sapien nec, tristique tempus felis. Ut porttitor auctor tellus in imperdiet. Ut blandit tincidunt augue, quis fringilla nunc tincidunt sed. Vestibulum auctor euismod nisi. Nullam tincidunt est in mi tincidunt dictum. Sed consectetur aliquet velit ut ornare.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam at enim id lorem tempus egestas a non ipsum. Maecenas imperdiet ante quam, at varius lorem molestie vel. Sed at eros consequat, varius tellus et, auctor felis. Donec pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec sit amet massa purus. Nunc sem lectus, bibendum a sapien nec, tristique tempus felis. Ut porttitor auctor tellus in imperdiet. Ut blandit tincidunt augue, quis fringilla nunc tincidunt sed. Vestibulum auctor euismod nisi. Nullam tincidunt est in mi tincidunt dictum. Sed consectetur aliquet velit ut ornare.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam at enim id lorem tempus egestas a non ipsum. Maecenas imperdiet ante quam, at varius lorem molestie vel. Sed at eros consequat, varius tellus et, auctor felis. Donec pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec sit amet massa purus. Nunc sem lectus, bibendum a sapien nec, tristique tempus felis. Ut porttitor auctor tellus in imperdiet. Ut blandit tincidunt augue, quis fringilla nunc tincidunt sed. Vestibulum auctor euismod nisi. Nullam tincidunt est in mi tincidunt dictum. Sed consectetur aliquet velit ut ornare.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam at enim id lorem tempus egestas a non ipsum. Maecenas imperdiet ante quam, at varius lorem molestie vel. Sed at eros consequat, varius tellus et, auctor felis. Donec pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec sit amet massa purus. Nunc sem lectus, bibendum a sapien nec, tristique tempus felis. Ut porttitor auctor tellus in imperdiet. Ut blandit tincidunt augue, quis fringilla nunc tincidunt sed. Vestibulum auctor euismod nisi. Nullam tincidunt est in mi tincidunt dictum. Sed consectetur aliquet velit ut ornare.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam at enim id lorem tempus egestas a non ipsum. Maecenas imperdiet ante quam, at varius lorem molestie vel. Sed at eros consequat, varius tellus et, auctor felis. Donec pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec sit amet massa purus.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam at enim id lorem tempus egestas a non ipsum. Maecenas imperdiet ante quam, at varius lorem molestie vel. Sed at eros consequat, varius tellus et, auctor felis. Donec pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec sit amet massa purus.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam at enim id lorem tempus egestas a non ipsum. Maecenas imperdiet ante quam, at varius lorem molestie vel. Sed at eros consequat, varius tellus et, auctor felis. Donec pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec sit amet massa purus.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam at enim id lorem tempus egestas a non ipsum. Maecenas imperdiet ante quam, at varius lorem molestie vel. Sed at eros consequat, varius tellus et, auctor felis. Donec pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec sit amet massa purus.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam at enim id lorem tempus egestas a non ipsum. Maecenas imperdiet ante quam, at varius lorem molestie vel. Sed at eros consequat, varius tellus et, auctor felis. Donec pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec sit amet massa purus.
More examples in a larger viewport
See the PageLayout Storybook stories.
Props
PageLayout
| Name | Default | Description |
|---|---|---|
containerWidth | 'xlarge' | | 'full' | 'medium' | 'large' | 'xlarge'The maximum width of the page container. |
padding | 'normal' | | 'none' | 'condensed' | 'normal'The spacing between the outer edges of the page container and the viewport |
columnGap | 'normal' | | 'none' | 'condensed' | 'normal' |
rowGap | 'normal' | | 'none' | 'condensed' | 'normal' |
PageLayout.Header
| Name | Default | Description |
|---|---|---|
aria-label | string | undefinedA unique label for the rendered banner landmark | |
aria-labelledby | string | undefinedAn id to an element which uniquely labels the rendered banner landmark | |
padding | 'none' | | 'none' | 'condensed' | 'normal'The amount of padding inside the header. |
divider | 'none' | | 'none' | 'line' | { narrow?: | 'none' | 'line' | 'filled' regular?: | 'none' | 'line' wide?: | 'none' | 'line' } |
dividerWhenNarrow Deprecated | 'inherit' | | 'inherit' | 'none' | 'line' | 'filled'Use the divider prop with a responsive value instead. |
hidden | false | | boolean | { narrow?: boolean regular?: boolean wide?: boolean }Whether the header is hidden. |
PageLayout.Content
| Name | Default | Description |
|---|---|---|
aria-label | stringA unique label for the rendered main landmark | |
aria-labelledby | stringAn id to an element which uniquely labels the rendered main landmark | |
as | 'main' | React.ElementTypeChange the root node to another HTML element or custom component. |
width | 'full' | | 'full' | 'medium' | 'large' | 'xlarge'The maximum width of the content region. |
padding | 'none' | | 'none' | 'condensed' | 'normal'The amount of padding inside the content. |
hidden | false | | boolean | { narrow?: boolean regular?: boolean wide?: boolean }Whether the content is hidden. |
PageLayout.Pane
| Name | Default | Description |
|---|---|---|
aria-label | string | undefinedLabel for the pane. Required if the pane overflows and doesn't have aria-labelledby. | |
aria-labelledby | string | undefinedId of an element that acts as a label for the pane. Required if the pane overflows and doesn't have aria-label. | |
width | 'medium' | | 'small' | 'medium' | 'large' | { min: string max: string default: string }The width of the pane. If using custom widths, provide an object with keys 'min', 'max' and 'default'. |
minWidth | 256 | numberThe minimum width of the pane. |
resizable | false | booleanWhen true, the pane may be resized by the user. Uses localStorage persistence by default. Note: with default persistence in SSR, the server-rendered width may differ from the stored client width, causing a brief layout shift on hydration. Use |
currentWidth | number | undefinedCurrent/controlled width value in pixels. Required when | |
onResizeEnd | (width: number) => voidCallback fired when a resize operation ends (drag release or keyboard key up). When provided, replaces localStorage persistence. Requires | |
widthStorageKey | 'paneWidth' | stringlocalStorage key used to persist the pane width across sessions. Only applies when |
sticky | false | booleanWhether the pane should stick to the top of the screen while the content scrolls. |
offsetHeader | 0 | number | stringUse offsetHeader along with the sticky prop to push the sticky pane down to make room for a sticky header if necessary. Use the type |
padding | 'none' | | 'none' | 'condensed' | 'normal'The amount of padding inside the pane. |
divider | 'none' | | 'none' | 'line' | { narrow?: | 'none' | 'line' | 'filled' regular?: | 'none' | 'line' wide?: | 'none' | 'line' } |
dividerWhenNarrow Deprecated | 'inherit' | | 'inherit' | 'none' | 'line' | 'filled'Use the divider prop with a responsive value instead. |
hidden | false | | boolean | { narrow?: boolean regular?: boolean wide?: boolean }Whether the pane is hidden. |
position | 'end' | 'start' | { narrow?: 'end' | 'start'; regular?: 'end' | 'start'; wide?: 'end' | 'start'; }Which side of the page the pane should be on. Can be changed for different viewport widths. | |
ref | React.RefObject<HTMLDivElement> |
PageLayout.Sidebar
| Name | Default | Description |
|---|---|---|
aria-label | string | undefinedA unique label for the sidebar region. | |
aria-labelledby | string | undefinedAn id to an element which uniquely labels the sidebar region. | |
position | 'start' | 'start' | 'end'Position of the sidebar relative to the page layout. The sidebar spans the full height of the layout, adjacent to the header, content, and footer. |
width | 'medium' | | 'small' | 'medium' | 'large' | { min: string max: string default: string }The width of the sidebar. If using custom widths, provide an object with keys 'min', 'max' and 'default'. |
minWidth | 256 | numberMinimum width of the sidebar when resizable. |
resizable | false | booleanWhen true, the sidebar may be resized by the user. Width is persisted to localStorage by default. |
padding | 'none' | | 'none' | 'condensed' | 'normal'The amount of padding inside the sidebar. |
divider | 'none' | | 'none' | 'line'Divider style between the sidebar and the rest of the layout. |
sticky | false | booleanWhether the sidebar sticks to the viewport when scrolling. When enabled, the sidebar uses position: sticky with top: 0 and height: 100vh. |
responsiveVariant | 'default' | | 'default' | 'fullscreen'Controls sidebar behavior at narrow viewport widths (below 768px). 'default' retains its normal inline layout. 'fullscreen' expands to cover the full viewport like a dialog overlay. |
hidden | false | | boolean | { narrow?: boolean regular?: boolean wide?: boolean }Whether the sidebar is hidden. |
PageLayout.Footer
| Name | Default | Description |
|---|---|---|
aria-label | string | undefinedA unique label for the rendered contentinfo landmark | |
aria-labelledby | string | undefinedAn id to an element which uniquely labels the rendered contentinfo landmark | |
padding | 'none' | | 'none' | 'condensed' | 'normal'The amount of padding inside the footer. |
divider | 'none' | | 'none' | 'line' | { narrow?: | 'none' | 'line' | 'filled' regular?: | 'none' | 'line' wide?: | 'none' | 'line' } |
dividerWhenNarrow Deprecated | 'inherit' | | 'inherit' | 'none' | 'line' | 'filled'Use the divider prop with a responsive value instead. |
hidden | false | | boolean | { narrow?: boolean regular?: boolean wide?: boolean }Whether the footer is hidden. |