Components

App Layout

Header, content, sidebars, and footer in one application shell.

AppLayout arranges a header, main content, sidebars, and footer. Add only the slots you need. Use Sidebar in either side slot for collapse, resizing, and mobile dialogs.

Anatomy

  • #header: Optional header above the workspace or just the content column.
  • #left: Optional left region. A Sidebar supplies its own width and responsive behavior.
  • #default: Main content. This region scrolls independently by default.
  • #right: Optional right region, with independent sidebar state.
  • #footer: Optional footer below the workspace or just the content column.

Every slot receives { mainId, layout, scroll }. No layout sub-components are required. The generated main element and keyboard skip link share a unique ID.

Usage

In the default mode, main content scrolls while the header, sidebars, and footer stay in place. Try the Navigation button to collapse the sidebar. On a narrow browser window, it opens a mobile dialog instead.

Skip to content
WorkspaceHeader

Projects

Main · Scroll here

Recent work across your team.

  • WebsiteIn progress
  • Customer portalIn progress
  • APIIn progress
  • DocumentationIn review
  • Mobile appIn review
  • Design systemIn review
All changes savedFooter

The preview is styled for this documentation. Code examples show the component structure and behavior without the demo's visual classes. See Styling for ui and CSS hooks.

How regions fit together

The default arrangement is a full-width header, a middle row containing left / main / right, and a full-width footer. Empty slots do not leave empty columns or bars.

SettingWhat changes
header: 'full' / footer: 'full'The bar spans the layout, including the sidebars.
header: 'content' / footer: 'content'The bar spans only main. Sidebars extend alongside it.
header: 'left' / footer: 'left'The bar spans left and main. The right sidebar extends alongside it.
header: 'right' / footer: 'right'The bar spans main and right. The left sidebar extends alongside it.
left: 'inline' / right: 'inline'The sidebar takes space beside main.
left: 'overlay' / right: 'overlay'The sidebar covers main without narrowing it.
scroll="content"Main scrolls independently inside the shell.
scroll="page"The layout follows document flow. Bars can be sticky.

Widths come from the contents of each side slot. Header and footer heights are measured automatically. Each Sidebar has its own controller; collapsing one does not collapse the other.

Layout Builder

Open the Layout Builder to choose regions, arrange both sidebars, test mobile dialogs, and generate Vue code without the preview's styling. For external sidebar controls, see useSidebar.

Examples

Use content when sidebars should extend alongside the bars. full spans all three columns. Left and right widths follow the elements placed in those slots, including Sidebar resize and collapse transitions.

Skip to content
WorkspaceHeader

Projects

Main · Scroll here

Recent work across your team.

  • WebsiteIn progress
  • Customer portalIn progress
  • APIIn progress
  • DocumentationIn review
  • Mobile appIn review
  • Design systemIn review
All changes savedFooter

Choose left or right to span main plus only that side. Header and footer are independent, so either sidebar can extend alongside one bar, both bars, or neither. These values refer to the named left and right slots.

Skip to content
WorkspaceHeader

Projects

Main · Scroll here

Recent work across your team.

  • WebsiteIn progress
  • Customer portalIn progress
  • APIIn progress
  • DocumentationIn review
  • Mobile appIn review
  • Design systemIn review
All changes savedFooter

For a right sidebar beside header, main, and footer, set both bars to left. For a left sidebar beside all three, set both to right.

Page scrolling with sticky regions

Set scroll="page" for document scrolling. Enable stickiness independently for header, footer, and side regions. stickyLeft and stickyRight override stickySides for each inline side. Sticky side offsets track only the bars that cover that side, including changes to their heights. As with native CSS sticky positioning, the nearest scrolling ancestor determines where regions stick. Footer remains at its natural place at the end of the page until it reaches its sticky boundary.

The contained preview scrolls as a whole; its header stays visible. In a full-screen application, the document scrolls instead.

Skip to content
WorkspaceHeader

Projects

Main · Scroll the preview

Recent work across your team.

  • WebsiteIn progress
  • Customer portalIn progress
  • APIIn progress
  • DocumentationIn review
  • Mobile appIn review
  • Design systemIn review
All changes savedFooter

Contained workspace

Disable viewport when embedding a shell inside another page. Content-scrolling mode then uses the parent's height. Supply a definite height on that parent, or override the root height through class / ui.root. Nested previews should use main-as="div" to avoid a second main landmark.

Skip to content
WorkspaceHeader

Projects

Main · Scroll here

Recent work across your team.

  • WebsiteIn progress
  • Customer portalIn progress
  • APIIn progress
  • DocumentationIn review
  • Mobile appIn review
  • Design systemIn review

Overlay sides

An overlay side does not reserve a grid column. It sits over main content, beneath full-width bars. Use Sidebar's off-canvas collapse and external controls to show or hide it. Desktop overlay placement is non-modal; mobile Sidebar behavior remains modal with focus trapping and dismissal. Supply a background on the sidebar panel so underlying content does not show through.

Try Navigation to collapse the overlay, then reopen it. Main keeps the same width. This preview starts expanded so you can see the overlay placement.

Skip to content
WorkspaceHeader

Projects

Main · Scroll here

Recent work across your team.

  • WebsiteIn progress
  • Customer portalIn progress
  • APIIn progress
  • DocumentationIn review
  • Mobile appIn review
  • Design systemIn review
All changes savedFooter

Route handling, navigation selection, and persistence remain application-owned. For controller methods and mobile dismissal, see Sidebar.

Accessibility and Keyboard

The default shell renders one header, main, and footer. Side wrappers are plain div elements so a Sidebar's aside or a consumer-owned nav does not receive duplicate landmark wrappers. Give each navigation or inspector its own accessible name.

Key / actionBehavior
TabReaches the skip link, then application controls in DOM order: header, left, main, right, footer. Main is a tab stop in content-scrolling mode so keyboard users can scroll it.
Enter on skip linkMoves focus to main without changing the URL or resetting the workspace scroll position.
Page Up / Down, Space, arrowsNative scrolling when focus is inside the scrollable content. Controls retain their own keyboard behavior.

main-as="div" is intended for nested previews or a shell inside an existing main landmark. focusMain() is exposed for applications that move focus after a route change. AppLayout itself does not observe routes.

API

Props

PropTypeDefaultDescription
asstring | Component"div"Outer root element.
mainAsstring | Component"main"Content element; use a native tag for the exposed focus helper.
layoutAppLayoutConfigSee belowRegion span and side placement. Partial objects keep defaults for omitted keys.
scroll"content" | "page""content"Independent main scrolling or document flow.
viewportbooleantrueDynamic viewport height in content mode; minimum viewport height in page mode.
stickyHeaderbooleanfalseSticky header in page mode.
stickyFooterbooleanfalseSticky footer in page mode.
stickySidesbooleanfalseSticky inline sides in page mode.
stickyLeftbooleanstickySidesOverride stickiness for the inline left side in page mode. Explicit false disables it.
stickyRightbooleanstickySidesOverride stickiness for the inline right side in page mode. Explicit false disables it.
safeAreabooleantrueOuter device safe-area padding. Consumer padding utilities can override it.
mainIdstringGeneratedMain ID and skip-link target. Keep explicit IDs unique.
mainLabelstring-Accessible name on content element.
skipLinkbooleantrueRender the keyboard skip link.
skipLabelstring"Skip to content"Skip-link text, including localization.
uiAppLayoutUi-Classes for generated parts.

Layout Options

KeyValuesDefaultDescription
header"full" | "content" | "left" | "right""full"All columns, main only, main plus left, or main plus right.
footer"full" | "content" | "left" | "right""full"All columns, main only, main plus left, or main plus right.
left"inline" | "overlay""inline"Reserve left width or cover main content.
right"inline" | "overlay""inline"Reserve right width or cover main content.

Slots

All five slots receive mainId: string, resolved layout: Required<AppLayoutConfig>, and scroll: AppLayoutScroll. Slots supply content inside generated region wrappers. Omitted region slots produce no wrappers. Slot-owned controls retain their own event handlers and accessibility.

Exposed Methods

MemberTypeDescription
mainHTMLElement | nullMain element after mounting.
focusMain()() => voidFocus main while preserving scroll position.

AppLayout has no value model or change emits. It derives geometry from props, slots, and region measurements; Sidebar models remain on Sidebar.

UI Options

KeyElement
rootOuter CSS grid.
skipLinkKeyboard skip link.
headerHeader wrapper.
leftLeft region wrapper.
mainScrollable main content.
rightRight region wrapper.
footerFooter wrapper.

Direct class and ui.root both style the single outer root. AppLayout supplies only positioning, scrolling, visibility, and safe-area mechanics. Supply backgrounds, padding, borders, typography, and visible focus styles through ui.

Styling Hooks

UI keyCSS classData attributes
rootakaza-app-layoutdata-akaza-scroll="content|page", data-akaza-viewport, data-akaza-safe-area, data-akaza-header="full|content|left|right", data-akaza-footer="full|content|left|right"
skipLinkakaza-app-layout-skip-linkNative :focus / :focus-visible.
headerakaza-app-layout-headerdata-akaza-span="full|content|left|right", data-akaza-sticky
leftakaza-app-layout-leftdata-akaza-side="left", data-akaza-mode="inline|overlay", data-akaza-sticky
mainakaza-app-layout-mainNative :focus / :focus-visible.
rightakaza-app-layout-rightdata-akaza-side="right", data-akaza-mode="inline|overlay", data-akaza-sticky
footerakaza-app-layout-footerdata-akaza-span="full|content|left|right", data-akaza-sticky

No exclusive interaction state exists on AppLayout, so there is no artificial data-akaza-state.

CSS Variables

VariableValue / default
--akaza-app-layout-header-heightMeasured header border-box height.
--akaza-app-layout-footer-heightMeasured footer border-box height.
--akaza-app-layout-viewport-height100dvh. Height basis for sticky sides; set it to the parent's height for contained layouts.
--akaza-app-layout-left-top, --akaza-app-layout-right-topHeader offset for each side; zero if header does not cover it.
--akaza-app-layout-left-bottom, --akaza-app-layout-right-bottomFooter offset for each side; zero if footer does not cover it.
--akaza-app-layout-left-sticky-top, --akaza-app-layout-right-sticky-topHeader offset for each sticky side when that bar is sticky and covers the side.
--akaza-app-layout-left-sticky-bottom, --akaza-app-layout-right-sticky-bottomFooter offset for each sticky side when that bar is sticky and covers the side.
--akaza-app-layout-side-top, --akaza-app-layout-side-bottomOn each side wrapper, aliases of its own overlay offsets.
--akaza-app-layout-sticky-top, --akaza-app-layout-sticky-bottomOn each side wrapper, aliases of its own sticky offsets.
--akaza-app-layout-side-z-index1
--akaza-app-layout-bar-z-index2
--akaza-app-layout-skip-z-index3

Overlay side regions use local stacking inside the isolated shell. Sidebar mobile dialogs and NavigationMenu flyouts keep their existing Teleport behavior outside the shell. Use scroll="page" if non-teleported popups need to escape the shell's clipped boundary.