Documentation

Documentation versions (currently viewingVaadin 24)

App Layout

App Layout is a component for building common application layouts.

App Layout is a component for building common application layouts.

Important
Scaled down examples
The examples on this page are scaled down so that their viewport-size-dependent behavior can be demonstrated. Some examples also change their behavior based on your browser viewport size.
Open in a
new tab
<vaadin-app-layout>
  <vaadin-drawer-toggle slot="navbar"></vaadin-drawer-toggle>
  <h1 slot="navbar">MyApp</h1>
  <vaadin-scroller slot="drawer" class="p-s">
    <vaadin-side-nav>
      <vaadin-side-nav-item path="/dashboard">
        <vaadin-icon icon="vaadin:dashboard" slot="prefix"></vaadin-icon>
        Dashboard
      </vaadin-side-nav-item>
      <vaadin-side-nav-item path="/orders">
        <vaadin-icon icon="vaadin:cart" slot="prefix"></vaadin-icon>
        Orders
      </vaadin-side-nav-item>
      <vaadin-side-nav-item path="/customers">
        <vaadin-icon icon="vaadin:user-heart" slot="prefix"></vaadin-icon>
        Customers
      </vaadin-side-nav-item>
      <vaadin-side-nav-item path="/products">
        <vaadin-icon icon="vaadin:package" slot="prefix"></vaadin-icon>
        Products
      </vaadin-side-nav-item>
      <vaadin-side-nav-item path="/documents">
        <vaadin-icon icon="vaadin:records" slot="prefix"></vaadin-icon>
        Documents
      </vaadin-side-nav-item>
      <vaadin-side-nav-item path="/tasks">
        <vaadin-icon icon="vaadin:list" slot="prefix"></vaadin-icon>
        Tasks
      </vaadin-side-nav-item>
      <vaadin-side-nav-item path="/analytics">
        <vaadin-icon icon="vaadin:chart" slot="prefix"></vaadin-icon>
        Analytics
      </vaadin-side-nav-item>
    </vaadin-side-nav>
  </vaadin-scroller>
</vaadin-app-layout>

The layout consists of three sections: a horizontal navigation bar (navbar), a collapsible navigation drawer (drawer) and a content area. An application’s main navigation blocks should be positioned in the navbar and/or drawer, whereas views are rendered in the content area.

App Layout is responsive and adjusts automatically to fit desktop, tablet, and mobile screen sizes.

The navbar can be located on top or to the side of the drawer.

When put on top, the navbar is typically used as an application header. Application headers contain, for example, the application’s name and branding, as well as actions that apply to the entire application, such as notifications, settings, etc.

Open in a
new tab
<vaadin-app-layout>
  <vaadin-drawer-toggle slot="navbar"></vaadin-drawer-toggle>
  <h1 slot="navbar">MyApp</h1>
  <vaadin-scroller slot="drawer" class="p-s">
    <vaadin-side-nav>
      <vaadin-side-nav-item path="/dashboard">
        <vaadin-icon icon="vaadin:dashboard" slot="prefix"></vaadin-icon>
        <span>Dashboard</span>
      </vaadin-side-nav-item>
      <vaadin-side-nav-item path="/orders">
        <vaadin-icon icon="vaadin:cart" slot="prefix"></vaadin-icon>
        <span>Orders</span>
      </vaadin-side-nav-item>
    </vaadin-side-nav>
  </vaadin-scroller>
</vaadin-app-layout>

When placed to the side, the navbar is often seen as a view header, housing the view’s title, and actions and secondary navigation that relate only to the current view.

Open in a
new tab
<vaadin-app-layout primary-section="drawer">
  <vaadin-drawer-toggle slot="navbar"></vaadin-drawer-toggle>
  <h1 slot="navbar">Dashboard</h1>
  <vaadin-scroller slot="drawer" class="p-s">
    <vaadin-side-nav>
      <vaadin-side-nav-item path="/dashboard">
        <vaadin-icon icon="vaadin:dashboard" slot="prefix"></vaadin-icon>
        Dashboard
      </vaadin-side-nav-item>
      <vaadin-side-nav-item path="/orders">
        <vaadin-icon icon="vaadin:cart" slot="prefix"></vaadin-icon>
        Orders
      </vaadin-side-nav-item>
    </vaadin-side-nav>
  </vaadin-scroller>
</vaadin-app-layout>

Drawer Toggle

Show and hide the drawer using a Drawer Toggle (or a Button). The Drawer Toggle (☰) should always be accessible (unless the drawer is empty) and is most often situated in the navbar.

Scrolling Behavior

Depending on whether App Layout has a defined height, the way the content inside the layout scrolls can differ.

Auto Height

When the App Layout has an undefined/auto height, which is the default behavior, the <body> element is the scrolling container for the content inside the layout.

Open in a
new tab
<vaadin-app-layout>
  <h1 slot="navbar">MyApp</h1>
  <vaadin-grid .items="${this.items}" all-rows-visible>
    <vaadin-grid-column path="firstName"></vaadin-grid-column>
    <vaadin-grid-column path="lastName"></vaadin-grid-column>
    <vaadin-grid-column path="email"></vaadin-grid-column>
    <vaadin-grid-column path="profession"></vaadin-grid-column>
  </vaadin-grid>
</vaadin-app-layout>

The vertical scrollbar crosses the App Layout navbar and the content flows under it, allowing for translucent visual styles. Mobile browsers collapse and expand their toolbars when the user scrolls down and up, respectively. On iOS, you can tap the status bar (signal strength, battery, clock, etc.) to scroll back to the top of the page/view.

This behavior isn’t compatible with vertically scrollable Grids, or other scrolling containers within the content area whose height is 100%. To support those, define 100% height for the App Layout.

Full Height (100%)

To allow a nested component to take all the available vertical space inside the App Layout, you need to set an explicit height for the layout, commonly 100%. A common use case is to let a data grid fill the entire content area.

Note
Make sure all parent components/elements have 100% height
The full hierarchy of components from the App Layout to the <body> element need to have 100% height.
Open in a
new tab
<vaadin-app-layout style="height: 100%;">
  <h1 slot="navbar">MyApp</h1>
  <vaadin-grid .items="${this.items}" style="height: 100%;" theme="no-border">
    <vaadin-grid-column path="firstName"></vaadin-grid-column>
    <vaadin-grid-column path="lastName"></vaadin-grid-column>
    <vaadin-grid-column path="email"></vaadin-grid-column>
    <vaadin-grid-column path="profession"></vaadin-grid-column>
  </vaadin-grid>
</vaadin-app-layout>

The vertical scrollbar stays within the layout content area, and mobile browsers don’t collapse their toolbars when the content area is scrolled down.

Bottom Navbar on Small Touchscreens

When the navbar is used for navigation, the touch-optimized navbar slot can be used to provide a separate version of the navigation at the bottom of the UI, optimized for mobile phones.

Open in a
new tab
<!-- --vaadin-app-layout-touch-optimized is only enforced as part of this example -->
<vaadin-app-layout style="--vaadin-app-layout-touch-optimized: true">
  <h1 slot="navbar">MyApp</h1>
  <vaadin-horizontal-layout
    slot="navbar touch-optimized"
    class="w-full justify-evenly self-stretch"
  >
    <a href="/dashboard" aria-label="Dashboard" class="text-secondary px-l flex items-center">
      <vaadin-icon icon="vaadin:dashboard"></vaadin-icon>
    </a>
    <a href="/orders" aria-label="Orders" class="text-secondary px-l flex items-center">
      <vaadin-icon icon="vaadin:cart"></vaadin-icon>
    </a>
  </vaadin-horizontal-layout>
  <div class="content">
    <h2>View title</h2>
    <p>View content</p>
  </div>
</vaadin-app-layout>

Best Practices

Make the choice between navbar and drawer based primarily on the number of items placed in it.

The navbar is a good choice for a small number of items (3–5), as these can fit into the viewport without scrolling.

Open in a
new tab
<vaadin-app-layout>
  <h1 slot="navbar">MyApp</h1>
  <vaadin-horizontal-layout slot="navbar" class="h-m w-full justify-center gap-s">
    <a
      href="/dashboard"
      class="flex items-center px-m text-secondary font-medium"
      style="text-decoration: none"
    >
      Dashboard
    </a>
    <a
      href="/orders"
      class="flex items-center px-m text-secondary font-medium"
      style="text-decoration: none"
    >
      Orders
    </a>
  </vaadin-horizontal-layout>
</vaadin-app-layout>

When more items need to be displayed, or if small-screen support is a priority, the drawer is a better choice, as it can accommodate a longer list of links without scrolling, and collapses into a hamburger menu on small screens. Furthermore, a vertical list of items is easier for the user to scan.

Open in a
new tab
<vaadin-app-layout primary-section="drawer">
  <vaadin-drawer-toggle slot="navbar"></vaadin-drawer-toggle>
  <h1 slot="navbar">Dashboard</h1>
  <vaadin-scroller slot="drawer" class="p-s">
    <vaadin-side-nav>
      <vaadin-side-nav-item path="/dashboard">
        <vaadin-icon icon="vaadin:dashboard" slot="prefix"></vaadin-icon>
        Dashboard
      </vaadin-side-nav-item>
      <vaadin-side-nav-item path="/orders">
        <vaadin-icon icon="vaadin:cart" slot="prefix"></vaadin-icon>
        Orders
      </vaadin-side-nav-item>
    </vaadin-side-nav>
  </vaadin-scroller>
</vaadin-app-layout>

For applications that require multilevel or hierarchical navigation, use the drawer to (at least) house the first level. The secondary (and tertiary) navigation items can be placed in either the drawer or the navbar.

Open in a
new tab
<vaadin-app-layout primary-section="drawer">
  <h1 slot="drawer">MyApp</h1>
  <vaadin-scroller slot="drawer" class="p-s">
    <vaadin-side-nav>
      <vaadin-side-nav-item path="/dashboard">
        <vaadin-icon icon="vaadin:dashboard" slot="prefix"></vaadin-icon>
        Dashboard
      </vaadin-side-nav-item>
      <vaadin-side-nav-item path="/orders">
        <vaadin-icon icon="vaadin:cart" slot="prefix"></vaadin-icon>
        Orders
      </vaadin-side-nav-item>
    </vaadin-side-nav>
  </vaadin-scroller>
  <vaadin-vertical-layout slot="navbar">
    <vaadin-horizontal-layout style="align-items: center;">
      <vaadin-drawer-toggle></vaadin-drawer-toggle>
      <h2>Orders</h2>
    </vaadin-horizontal-layout>
    <vaadin-horizontal-layout id="navigation" class="h-m justify-center gap-s">
      <a
        href="/all"
        class="flex items-center px-m text-secondary font-medium"
        style="text-decoration: none"
        >All</a
      >
      <a
        href="/open"
        class="flex items-center px-m text-secondary font-medium"
        style="text-decoration: none"
        >Open</a
      >
    </vaadin-horizontal-layout>
  </vaadin-vertical-layout>
</vaadin-app-layout>

3005EA19-8E28-4BF2-8A0A-FC3F46C04F1B