Skip to main content
The Sidebar component provides a responsive layout system for admin dashboards and documentation sites. It features a sticky sidebar that collapses on mobile and optional always-collapsible behavior.

Basic Usage

Use data-sidebar-layout on a container (typically <body>) with <aside data-sidebar> for the sidebar and <main> for content.
<div data-sidebar-layout>
  <aside data-sidebar>
    <nav>
      <ul>
        <li><a href="#" aria-current="page">Home</a></li>
        <li><a href="#">Users</a></li>
        <li>
          <details open>
            <summary>Settings</summary>
            <ul>
              <li><a href="#">General</a></li>
              <li><a href="#">Security</a></li>
              <li><a href="#">Billing</a></li>
            </ul>
          </details>
        </li>
      </ul>
    </nav>
    <footer>
      <button class="outline sm" style="width: 100%;">Logout</button>
    </footer>
  </aside>
  <main>
    <div style="padding: var(--space-3)">Main content area. Scrolls with the page body.</div>
  </main>
</div>

Features

Sticky Positioning

Sidebar stays fixed while main content scrolls

Mobile Responsive

Becomes a slide-out overlay on screens ≤768px

Collapsible Sections

Use <details> elements for nested navigation

Always-Collapsible

Optional mode to collapse sidebar on all screen sizes

Structure

1

Layout Container

Add data-sidebar-layout to your container (usually <body>)
2

Sidebar Element

Create <aside data-sidebar> with header, nav, and footer sections
3

Main Content

Add <main> element for your page content
4

Toggle Button

Include <button data-sidebar-toggle> to control sidebar visibility

Attributes

data-sidebar-layout
attribute
required
Applied to the container element. Creates the grid layout for sidebar + main content.
data-sidebar-layout='always'
attribute
Makes the sidebar collapsible at all screen sizes (not just mobile).
data-sidebar
attribute
required
Applied to the <aside> element. Marks it as the sidebar.
data-sidebar-toggle
attribute
required
Applied to a button. Toggles the sidebar open/closed.
data-sidebar-open
attribute
Automatically applied to the layout when sidebar is collapsed (closed). Used internally.
data-topnav
attribute
Applied to a <nav> element for a full-width sticky top navigation bar.

Always-Collapsible Mode

Set data-sidebar-layout="always" to keep the toggle visible on all screen sizes:
<body data-sidebar-layout="always">
  <nav data-topnav>
    <button data-sidebar-toggle aria-label="Toggle menu"></button>
    <span>App Name</span>
  </nav>
  
  <aside data-sidebar>
    <!-- sidebar content -->
  </aside>
  
  <main>
    <!-- main content -->
  </main>
</body>
In always-collapsible mode, the toggle button remains visible on desktop screens, allowing users to collapse the sidebar for more content space.

With Top Navigation

Add data-topnav to a nav element for a full-width sticky top navigation bar. The sidebar will adjust to sit below it.
<body data-sidebar-layout>
  <nav data-topnav>
    <button data-sidebar-toggle aria-label="Toggle menu" class="outline"></button>
    <span>App Name</span>
  </nav>

  <aside data-sidebar>
    <header>Logo</header>
    <nav>...navigation...</nav>
    <footer>Actions</footer>
  </aside>

  <main>
    Main page content.
  </main>
</body>
The sidebar can contain three optional sections:
<aside data-sidebar>
  <header>
    <img src="logo.svg" alt="Company Logo" />
    <h2>App Name</h2>
  </header>
  <!-- nav and footer -->
</aside>
<aside data-sidebar>
  <nav>
    <ul>
      <li><a href="/" aria-current="page">Dashboard</a></li>
      <li><a href="/users">Users</a></li>
      <li>
        <details>
          <summary>Settings</summary>
          <ul>
            <li><a href="/settings/general">General</a></li>
            <li><a href="/settings/security">Security</a></li>
          </ul>
        </details>
      </li>
    </ul>
  </nav>
</aside>
<aside data-sidebar>
  <!-- header and nav -->
  <footer>
    <button class="outline" style="width: 100%;">Sign Out</button>
  </footer>
</aside>

Collapsible Navigation Groups

Use <details> elements for collapsible navigation sections:
<nav>
  <ul>
    <li><a href="#">Home</a></li>
    <li>
      <details open>
        <summary>Products</summary>
        <ul>
          <li><a href="#">All Products</a></li>
          <li><a href="#">Categories</a></li>
          <li><a href="#">Inventory</a></li>
        </ul>
      </details>
    </li>
    <li>
      <details>
        <summary>Settings</summary>
        <ul>
          <li><a href="#">Profile</a></li>
          <li><a href="#">Preferences</a></li>
        </ul>
      </details>
    </li>
  </ul>
</nav>
Add the open attribute to <details> to have sections expanded by default.

Responsive Behavior

Desktop (> 768px)

  • Sidebar is visible and sticky
  • Grid layout: 14rem sidebar + 1fr main content
  • Sidebar scrolls independently if content overflows

Mobile (≤ 768px)

  • Sidebar becomes a slide-out overlay
  • Hidden by default (off-screen)
  • Toggle button controls visibility
  • Clicking outside the sidebar closes it

Always-Collapsible Mode

  • Toggle button visible at all screen sizes
  • Sidebar can be collapsed on desktop
  • When collapsed: grid changes to 0px 1fr (sidebar hidden)

JavaScript Behavior

The sidebar uses a simple JavaScript handler for toggling:
// Automatically included in Oat UI
document.addEventListener('click', (e) => {
  const toggle = e.target.closest('[data-sidebar-toggle]');
  if (toggle) {
    const layout = toggle.closest('[data-sidebar-layout]');
    layout?.toggleAttribute('data-sidebar-open');
  }
});

Active Page Indicator

Use aria-current="page" on the active navigation link:
<nav>
  <ul>
    <li><a href="/" aria-current="page">Home</a></li>
    <li><a href="/users">Users</a></li>
    <li><a href="/settings">Settings</a></li>
  </ul>
</nav>

Styling

The sidebar uses CSS Grid and custom properties:
[data-sidebar-layout] {
  display: grid;
  grid-template-columns: 14rem 1fr;
  min-height: 100dvh;
  gap: var(--space-4);
}

[data-sidebar] {
  position: sticky;
  top: 0;
  height: 100dvh;
  background-color: var(--background);
  border-inline-end: 1px solid var(--border);
}

Accessibility

Add aria-label="Toggle menu" to the toggle button for screen readers.
Use aria-current="page" on the active navigation link to indicate the current page.
All interactive elements (links, buttons, details) are keyboard accessible.
When the sidebar opens on mobile, focus remains manageable and logical.

Best Practices

Logical Structure

Organize navigation in a clear hierarchy using nested lists and details

Consistent Width

Keep sidebar width reasonable (14rem default) for readability

Mobile First

Always test the slide-out behavior on mobile devices

Footer Actions

Place important actions (logout, settings) in the footer section

Full Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="path/to/oat.css">
  <title>Admin Dashboard</title>
</head>
<body data-sidebar-layout="always">
  <nav data-topnav>
    <button data-sidebar-toggle aria-label="Toggle menu" class="outline"></button>
    <a href="/">Dashboard</a>
  </nav>

  <aside data-sidebar>
    <header>
      <h2>My App</h2>
    </header>
    
    <nav>
      <ul>
        <li><a href="/" aria-current="page">Home</a></li>
        <li><a href="/analytics">Analytics</a></li>
        <li>
          <details open>
            <summary>Settings</summary>
            <ul>
              <li><a href="/settings/profile">Profile</a></li>
              <li><a href="/settings/team">Team</a></li>
              <li><a href="/settings/billing">Billing</a></li>
            </ul>
          </details>
        </li>
      </ul>
    </nav>
    
    <footer>
      <button class="outline small" style="width: 100%;">Sign Out</button>
    </footer>
  </aside>

  <main>
    <div style="padding: var(--space-6);">
      <h1>Dashboard</h1>
      <p>Main content goes here...</p>
    </div>
  </main>

  <script src="path/to/oat.js"></script>
</body>
</html>