Files
tabler/docs/content/ui/layout/page-layouts.mdx
T
codecalm 6481499ccd Add folded sidebar with flyout menus, pin toggle and light default
- navbar-folded / navbar-folded-hover with flyout submenus and persisted pin toggle
- sidebar refresh: light by default, 16rem wide, rounded inset pills, zero-jump fold
- demo pages, Theme Settings section, docs and btn-action usage rule
2026-08-20 22:27:53 +02:00

363 lines
15 KiB
Plaintext

---
title: Page layouts
summary: Learn how to build a sample version of the dashboard
description: Learn how to combine containers, navigation, and page structure to build a complete dashboard layout step by step.
related: [/ui/layout/page-headers, /ui/layout/navbars]
---
import Example from '@components/Example.astro'
import Icon from '@ui/Icon.astro'
Before you start with this section, make sure you have followed the [installation guideline](/ui/getting-started/installation).
## Sample layout
To create a sample version of the dashboard, you can use the following code snippet. This code snippet will help you to create a dashboard layout with a header.
<Example>
<div class="page">
<header class="navbar navbar-expand-sm d-print-none">
<div class="container-xl">
<h1 class="navbar-brand navbar-brand-autodark d-none-navbar-horizontal pe-0 pe-md-3">
<a href="#">
<img src="/static/logo.svg" width="110" height="32" alt="Tabler" class="navbar-brand-image" />
</a>
</h1>
<div class="navbar-nav flex-row order-md-last">
<div class="nav-item">
<a href="#" class="nav-link d-flex lh-1 text-reset p-0">
<span class="avatar avatar-sm" style="background-image: url(/static/avatars/002m.jpg)"></span>
<div class="d-none d-xl-block ps-2">
<div>Paweł Kuna</div>
<div class="mt-1 small text-secondary">UI Designer</div>
</div>
</a>
</div>
</div>
</div>
</header>
<div class="page-wrapper">
<main id="content" class="page-body">
<div class="container-xl">
<div class="row row-deck row-cards">
<div class="col-4">
<div class="card">
<div class="card-body" style="height: 10rem"></div>
</div>
</div>
<div class="col-4">
<div class="card">
<div class="card-body" style="height: 10rem"></div>
</div>
</div>
<div class="col-4">
<div class="card">
<div class="card-body" style="height: 10rem"></div>
</div>
</div>
<div class="col-12">
<div class="card">
<div class="card-body" style="height: 10rem"></div>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
</Example>
## Footer
Add a `footer` element with the `footer` class after `.page-wrapper` to close the page. `d-print-none` hides it when the page is printed, the same as the navbar. Use [`list-inline list-inline-dots`](/ui/components/list-group#inline-list) for the footer links.
<Example>
<footer class="footer footer-transparent d-print-none">
<div class="container-xl">
<div class="row text-center align-items-center flex-row-reverse">
<div class="col-lg-auto ms-lg-auto">
<ul class="list-inline list-inline-dots mb-0">
<li class="list-inline-item"><a href="#" class="link-secondary">Documentation</a></li>
<li class="list-inline-item"><a href="#" class="link-secondary">License</a></li>
<li class="list-inline-item"><a href="#" class="link-secondary">Source code</a></li>
</ul>
</div>
<div class="col-12 col-lg-auto mt-3 mt-lg-0">
<ul class="list-inline list-inline-dots mb-0">
<li class="list-inline-item"> Copyright &copy; 2026 <a href="#" class="link-secondary">Your company</a> . All rights reserved. </li>
<li class="list-inline-item"><a href="#" class="link-secondary">v1.0.0</a></li>
</ul>
</div>
</div>
</div>
</footer>
</Example>
`footer-transparent` drops the footer's own background, so it blends with the page behind it. Remove the class for a footer with a solid background, for example to visually separate it from the page body.
## Sidebar layout
To create a sidebar layout, you can use the following code snippet. This code snippet will help you to create a sidebar layout with a header.
<Example>
<div class="page">
<aside class="navbar navbar-vertical navbar-expand-sm position-absolute">
<div class="container-fluid">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar-menu" aria-controls="sidebar-menu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<h1 class="navbar-brand navbar-brand-autodark">
<a href="#">
<img src="/static/logo.svg" width="110" height="32" alt="Tabler" class="navbar-brand-image" />
</a>
</h1>
<div class="collapse navbar-collapse" id="sidebar-menu">
<ul class="navbar-nav pt-lg-3">
<li class="nav-item">
<a class="nav-link" href="./">
<span class="nav-link-title">Home</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<span class="nav-link-title">Link 1</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<span class="nav-link-title">Link 2</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<span class="nav-link-title">Link 3</span>
</a>
</li>
</ul>
</div>
</div>
</aside>
<div class="page-wrapper">
<div class="page-header d-print-none">
<div class="container-xl">
<div class="row g-2 align-items-center">
<div class="col">
<h2 class="page-title">Vertical layout</h2>
</div>
</div>
</div>
</div>
<main id="content" class="page-body">
<div class="container-xl">
<div class="row row-deck row-cards">
<div class="col-sm-6 col-lg-3">
<div class="card">
<div class="card-body" style="height: 10rem"></div>
</div>
</div>
<div class="col-sm-6 col-lg-3">
<div class="card">
<div class="card-body" style="height: 10rem"></div>
</div>
</div>
<div class="col-sm-6 col-lg-3">
<div class="card">
<div class="card-body" style="height: 10rem"></div>
</div>
</div>
<div class="col-sm-6 col-lg-3">
<div class="card">
<div class="card-body" style="height: 10rem"></div>
</div>
</div>
<div class="col-lg-6">
<div class="row row-cards">
<div class="col-12">
<div class="card">
<div class="card-body" style="height: 10rem"></div>
</div>
</div>
<div class="col-12">
<div class="card">
<div class="card-body" style="height: 10rem"></div>
</div>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="card">
<div class="card-body" style="height: 10rem"></div>
</div>
</div>
<div class="col-12">
<div class="card">
<div class="card-body" style="height: 10rem"></div>
</div>
</div>
<div class="col-md-12 col-lg-8">
<div class="card">
<div class="card-body" style="height: 10rem"></div>
</div>
</div>
<div class="col-md-6 col-lg-4">
<div class="card">
<div class="card-body" style="height: 10rem"></div>
</div>
</div>
<div class="col-md-6 col-lg-4">
<div class="card">
<div class="card-body" style="height: 10rem"></div>
</div>
</div>
<div class="col-md-12 col-lg-8">
<div class="card">
<div class="card-body" style="height: 10rem"></div>
</div>
</div>
<div class="col-12">
<div class="card">
<div class="card-body" style="height: 10rem"></div>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
</Example>
## Folded sidebar
Add `navbar-folded` to a vertical navbar to fold it into a narrow, icon-only rail. Link titles are hidden, icons are centered and submenus open as floating flyout menus next to the rail. The page content moves over automatically, so you get more space for your app.
The folded mode works only above the navbar's `navbar-expand-*` breakpoint. Below it, the sidebar keeps the standard mobile behavior with the toggler button.
Use `data-bs-auto-close="outside"` on submenu toggles in a folded sidebar, so an open flyout closes when the user clicks somewhere else.
<Example height="26rem">
<div class="page">
<aside class="navbar navbar-vertical navbar-expand-sm navbar-folded position-absolute">
<div class="container-fluid">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar-folded" aria-controls="sidebar-folded" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<h1 class="navbar-brand navbar-brand-autodark">
<a href="#">
<img src="/static/logo-small.svg" width="32" height="32" alt="Tabler" class="navbar-brand-image" />
</a>
</h1>
<div class="collapse navbar-collapse" id="sidebar-folded">
<ul class="navbar-nav pt-lg-3">
<li class="nav-item active">
<a class="nav-link" href="#" aria-current="page">
<span class="nav-link-icon"><Icon name="home" /></span>
<span class="nav-link-title">Home</span>
</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#sidebar-folded-reports" data-bs-toggle="dropdown" data-bs-auto-close="outside" role="button" aria-haspopup="true" aria-expanded="false">
<span class="nav-link-icon"><Icon name="chart-bar" /></span>
<span class="nav-link-title">Reports</span>
</a>
<div class="dropdown-menu">
<a class="dropdown-item" href="#">Overview</a>
<a class="dropdown-item" href="#">Sales</a>
<a class="dropdown-item" href="#">Traffic</a>
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<span class="nav-link-icon"><Icon name="settings" /></span>
<span class="nav-link-title">Settings</span>
</a>
</li>
</ul>
</div>
</div>
</aside>
<div class="page-wrapper">
<main id="content" class="page-body">
<div class="container-xl">
<div class="row row-deck row-cards">
<div class="col-6">
<div class="card">
<div class="card-body" style="height: 10rem"></div>
</div>
</div>
<div class="col-6">
<div class="card">
<div class="card-body" style="height: 10rem"></div>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
</Example>
Use a small, square logo in a folded sidebar. The brand area is only `4rem` wide, so a wide logo will be cropped.
A folded rail does not scroll. If your menu has more items than the screen can fit, use the hover variant below or keep the sidebar expanded.
### Unfold on hover
Use `navbar-folded-hover` instead of `navbar-folded` to get a folded rail that unfolds when the user hovers over it or moves keyboard focus into it. The expanded sidebar overlays the page content, so nothing moves around. This variant also restores scrolling of long menus while the sidebar is unfolded.
```html
<aside class="navbar navbar-vertical navbar-expand-lg navbar-folded-hover">
...
</aside>
```
### Pin button and saved state
To let users fold and unfold the sidebar at runtime, add a button with `data-bs-toggle="sidebar-folded"` anywhere on the page. A good place is the brand area: the logo stays on the start side and the pin button sits on the end side. The button is visible only while the sidebar is expanded. Unpinning folds the sidebar to the hover variant, so hovering the rail expands it again and shows the pin button:
```html
<div class="navbar-brand">
<a href="." aria-label="Tabler">
<svg class="navbar-brand-image"><!-- logo mark --></svg>
</a>
<button type="button" class="btn btn-action btn-sm" data-bs-toggle="sidebar-folded" aria-pressed="false" aria-label="Pin sidebar">
<svg><!-- pin icon --></svg>
</button>
</div>
```
Use a small, square logo mark in the brand area, so the logo does not jump when the sidebar folds and unfolds.
The button toggles the `data-bs-sidebar="folded-hover"` attribute on the `<html>` element, which folds every vertical navbar on the page. Set `data-bs-sidebar="folded"` yourself for a static rail that does not expand on hover. The choice is saved to `localStorage` under the `tabler-sidebar` key. The `tabler-theme.js` script applies the saved state before the page renders, so there is no flash of the wrong layout on reload. You can also set the state with the `?sidebar=folded` URL parameter.
After each toggle, Tabler dispatches a `tabler:sidebar-folded` event on `document`. Use it to resize charts or maps after the page content changes width:
```js
document.addEventListener('tabler:sidebar-folded', (event) => {
console.log(event.detail.folded) // true or false
myChart.resize()
})
```
You can also add tooltips with the link title to icon-only links, so users see the name of each item on hover.
## Accessibility
A layout is what a screen reader user navigates by, so the landmarks matter more here than on any single component.
- Use the real elements for the regions. Tabler's own layout renders `header` for the top bar, `aside` for the vertical navbar, `main` for `.page-body` and `footer` for the footer. The classes are styling; the elements are what create the landmarks.
- `.page-body` should be a `main`, and there is exactly one per page. It is the target the skip link points at.
- Start the page with a skip link, so keyboard users can jump past the navigation. Tabler ships one:
```html
<a href="#content" class="visually-hidden-focusable skip-link">Skip to main content</a>
...
<main id="content" class="page-body">
```
`visually-hidden-focusable` keeps the link out of the way until it takes focus, and then shows it.
- Label each navigation region. A page with a sidebar and a top bar has two `nav` elements, and `aria-label="Primary"` on one of them is what tells them apart.
- The navbar toggler needs `aria-controls` pointing at the collapsing element and a name such as "Toggle navigation". Bootstrap keeps `aria-expanded` in sync.
- Keep the DOM order close to the reading order. A sidebar that appears on the right visually should still come where it belongs in the markup.
- `d-print-none` on the navbar and the footer removes them from print, which is what you want - but check that nothing users need only exists there.