# Layout Blueprint

Every AdminLTE page follows the same structural blueprint: a wrapper that contains a header, a sidebar, a main content area, and (optionally) a footer. Understanding the four region classes is the difference between fighting the framework and using it productively.

##### The four regions

    ┌──────────────────────────────────────────┐
    │  .app-wrapper                            │
    │  ┌────────────────────────────────────┐  │
    │  │  .app-header                       │  │ ← topbar / navbar
    │  ├──────────┬─────────────────────────┤  │
    │  │          │                         │  │
    │  │  .app-   │   .app-main             │  │ ← page content
    │  │ sidebar  │                         │  │
    │  │          │                         │  │
    │  ├──────────┴─────────────────────────┤  │
    │  │  .app-footer (optional)            │  │
    │  └────────────────────────────────────┘  │
    └──────────────────────────────────────────┘

The wrapper is a CSS grid container, the four children are grid areas. You don’t have to know that to use it — the markup pattern alone is sufficient.

##### Minimal markup

    <body class="layout-fixed sidebar-expand-lg bg-body-tertiary">
      <div class="app-wrapper">
        <nav class="app-header navbar navbar-expand bg-body">…</nav>
        <aside class="app-sidebar bg-body-secondary shadow" data-bs-theme="dark">…</aside>
        <main class="app-main">…</main>
        <footer class="app-footer">…</footer>
      </div>
    </body>

Order inside `.app-wrapper` doesn’t matter — the grid template positions each child by its class. Use whatever order reads cleanly.

##### Region reference

###### `.app-wrapper`

The root container. Defines the grid template that positions header, sidebar, main, and footer. Always lives directly inside `<body>`.

You can add `.compact-mode` here (or anywhere up the tree) to reduce padding throughout the layout — useful for data-dense dashboards.

###### `.app-header`

The top bar. Use Bootstrap’s navbar classes (`navbar navbar-expand bg-body`) for the visual. The header is where the sidebar toggle button lives — wire it with `data-lte-toggle="sidebar"`:

    <a class="nav-link" data-lte-toggle="sidebar" href="#" role="button">
      <i class="bi bi-list"></i>
    </a>

By default the header scrolls with the page. Add `.fixed-header` to `<body>` to pin it.

###### `.app-sidebar`

The side rail. Always contains two children: `.sidebar-brand` (logo / app name) and `.sidebar-wrapper` (the scrollable nav region).

    <aside class="app-sidebar bg-body-secondary shadow" data-bs-theme="dark">
      <div class="sidebar-brand">
        <a href="/" class="brand-link">
          <span class="brand-text fw-light">My Dashboard</span>
        </a>
      </div>
      <div class="sidebar-wrapper">
        <nav class="mt-2">
          <ul class="nav sidebar-menu flex-column" data-lte-toggle="treeview" role="menu">
            <!-- nav items -->
          </ul>
        </nav>
      </div>
    </aside>

The `data-bs-theme="dark"` on the sidebar gives you the dark-sidebar-on-light-page look from the demos. Drop it for a light sidebar.

###### `.app-main`

The page content region. Almost always contains two children:

    <main class="app-main">
      <div class="app-content-header">
        <!-- page title + breadcrumb -->
      </div>
      <div class="app-content">
        <!-- page body, cards, tables, charts, etc. -->
      </div>
    </main>

`.app-content-header` is the title strip — typically an `<h3>` and a breadcrumb in a row. `.app-content` is everything below it. Both should wrap their children in `.container-fluid` (or `.container` for capped width).

###### `.app-footer` (optional)

A footer strip at the bottom of the wrapper:

    <footer class="app-footer">
      <div class="float-end d-none d-sm-inline">Version 4.0.0</div>
      <strong>&copy; 2026 Your Company</strong>
    </footer>

Add `.fixed-footer` to `<body>` to pin it to the bottom of the viewport.

##### Body-level layout modifiers

Layout behaviour is mostly controlled by classes on `<body>`, not `.app-wrapper`. The supported modifiers:

Class | What it does
--- | ---
`layout-fixed` | Sidebar gets its own scrollbar; only `.app-main` scrolls with the page
`fixed-header` | Sticky `.app-header` at the top; sidebar also pins (since v4.0.0)
`fixed-footer` | Sticky `.app-footer` at the bottom
`sidebar-expand-{sm,md,lg,xl,xxl}` | Breakpoint at which the sidebar transitions from off-canvas (mobile) to inline (desktop). `lg` is the default in the demos.
`sidebar-mini` | Collapses sidebar to icon-only mini state
`sidebar-mini sidebar-collapse` | Starts the page with the mini sidebar already collapsed
`sidebar-without-hover` | Disables the auto-expand-on-hover behaviour for the mini sidebar
`layout-rtl` | Mirrors the layout for right-to-left languages (also requires `.rtl.css` and `dir="rtl"` — see RTL Support)

These compose. The demo dashboards use `class="layout-fixed sidebar-expand-lg bg-body-tertiary"` — fixed-height with a desktop sidebar breakpoint at the `lg` (≥992px) boundary.

###### Layout variants demo

The Layout section of the demo site (`/layout/*.html` files) ships eleven pre-built combinations:

- Fixed Sidebar, Fixed Header, Fixed Footer, Fixed Complete
- Unfixed Sidebar, Sidebar Mini, Collapsed Sidebar, Collapsed without hover
- Layout Custom Area, Logo Switch, Layout RTL

##### Responsive behaviour

At and above your `sidebar-expand-*` breakpoint, the sidebar is inline — visible in the grid alongside `.app-main`. Below the breakpoint, it becomes off-canvas — hidden by default and slid in from the left when the user clicks the hamburger toggle.

Mobile-specific classes:

Class | When applied | Effect
--- | --- | ---
`sidebar-open` | Body — when the user explicitly opens the mobile sidebar | Slides the sidebar in over the content with an overlay
`sidebar-collapse` | Body — set automatically when the user closes the mobile sidebar | Hides the sidebar

These are managed by the PushMenu plugin — you don’t write them yourself.

##### Common pitfalls

- Forgetting `.container-fluid` inside `.app-content` — the content lands flush against the screen edge. Wrap your content cards in a container.
- Putting the sidebar toggle outside `.app-header` — it’ll still work, but the styling expects the navbar context.
- Mixing `.app-*` and `.main-*` classes — `.main-*` is the AdminLTE 3 naming. Don’t combine them. See Migration from v3.
- Using `position: fixed` on something inside `.app-main` — `layout-fixed` already gives `.app-main` `overflow: auto`. Children with `position: fixed` may behave unexpectedly. Use sticky positioning instead.
- Hardcoding sidebar width in custom CSS — the sidebar width is exposed via the SCSS variable `$lte-sidebar-width`. If you need to know it from JavaScript, read the rendered `.app-sidebar` element’s computed width.

##### Where to next

- Layout reference — the lower-level CSS classes and what they do
- PushMenu plugin — the sidebar toggle implementation
- Customization — how to change sidebar width, breakpoint, and colours