Skip to main content
Pricing

Page Layout

Free

The foundational shell for every page in the application. Provides named slots for header, main content, sidebar, and footer, using semantic landmark roles throughout. Automatically handles scroll containment and sticky positioning for the header and sidebar.

6 variants

Logo
HomeProductsAbout
J
Dashboard
Settings
Users
Reports
Action
© 2026 Company

Variants

VariantDescriptionWhen to use
Default
With SidebarLayout with a persistent left sidebar, sticky header, and scrollable main content.Use for app dashboards, settings pages, and documentation where navigation lives in the sidebar.
Full Width

Usage Guidelines

Do

Use semantic landmark elements — <header>, <main>, <aside>, <footer> — for each slot.

Don't

Nest multiple Page Layouts — there should be exactly one per route.

Do

Keep a single <main> element per page for screen reader navigation.

Don't

Use <div> instead of landmarks — screen readers rely on <main>, <aside>, etc.

Do

Allow the main content area to scroll independently from the sidebar.

Don't

Fix the footer to the bottom of the viewport — let it flow after content.

Do

Set a max-width on the content area to maintain readable line lengths.

Don't

Code

HTML
<div class="lex-page-layout">
  <header class="lex-page-layout__header" role="banner">
    <a href="#main-content" class="lex-skip-link">Skip to main content</a>
    <nav aria-label="Main navigation">
      <ul>
        <li><a href="/dashboard">Dashboard</a></li>
        <li><a href="/settings">Settings</a></li>
      </ul>
    </nav>
  </header>

  <div class="lex-page-layout__body">
    <aside class="lex-page-layout__sidebar" aria-label="Page navigation">
      <nav aria-label="Sidebar navigation">
        <ul>
          <li><a href="/settings/profile">Profile</a></li>
          <li><a href="/settings/billing">Billing</a></li>
          <li><a href="/settings/team">Team</a></li>
        </ul>
      </nav>
    </aside>

    <main class="lex-page-layout__main" id="main-content">
      <h1>Page title</h1>
      <p>Main page content goes here.</p>
    </main>
  </div>

  <footer class="lex-page-layout__footer" role="contentinfo">
    <p>&copy; 2026 Acme Inc.</p>
  </footer>
</div>
CSS Custom Properties
.lex-page-layout {
  display: grid;
  grid-template-rows: auto 1fr auto;
  min-height: 100dvh;
}

.lex-page-layout__header {
  position: sticky;
  top: 0;
  z-index: var(--lex-z-header, 100);
  background: var(--lex-bg-surface);
  border-bottom: 1px solid var(--lex-border-default);
  height: var(--lex-header-height, 56px);
  display: flex;
  align-items: center;
  padding: 0 var(--lex-space-24);
}

.lex-page-layout__body {
  display: flex;
  gap: var(--lex-layout-gap, 0);
}

.lex-page-layout__sidebar {
  width: var(--lex-layout-sidebar-width, 260px);
  flex-shrink: 0;
  position: sticky;
  top: var(--lex-header-height, 56px);
  height: calc(100dvh - var(--lex-header-height, 56px));
  overflow-y: auto;
  border-right: 1px solid var(--lex-border-default);
  padding: var(--lex-space-16);
}

.lex-page-layout__main {
  flex: 1;
  min-width: 0;
  padding: var(--lex-space-24);
  max-width: var(--lex-layout-max-width, 1200px);
}

.lex-page-layout__footer {
  border-top: 1px solid var(--lex-border-default);
  padding: var(--lex-space-16) var(--lex-space-24);
}

.lex-skip-link {
  position: absolute;
  left: -10000px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.lex-skip-link:focus {
  position: static;
  width: auto;
  height: auto;
}

@media (max-width: 768px) {
  .lex-page-layout__sidebar {
    display: none;
  }
}
React
// Using Lexicon CSS classes with React

export function DashboardPage() {
  return (
    <PageLayout
      header={<AppHeader />}
      sidebar={<DashboardNav />}
      footer={<AppFooter />}
      sidebarWidth={260}
      maxWidth={1200}
    >
      <h1>Dashboard</h1>
      <DashboardContent />
    </PageLayout>
  );
}

export function MarketingPage() {
  return (
    <PageLayout header={<MarketingHeader />} footer={<MarketingFooter />}>
      <HeroSection />
      <FeaturesSection />
      <PricingSection />
    </PageLayout>
  );
}

Design Tokens

TokenValue (dark)Value (light)CSS property
--lex-layout-max-widthwidth
--lex-layout-sidebar-widthwidth
--lex-layout-paddingpadding
--lex-layout-gapgap

Accessibility

  • Uses landmark roles: <header> with role="banner", <main>, <aside>, and <footer> with role="contentinfo".
  • Only one <main> element per page — screen readers use it as the primary content anchor.
  • Provide a "Skip to main content" link as the first focusable element in the header.
  • Sidebar should have aria-label to distinguish it from other <aside> elements.
  • Navigation regions need distinct aria-label values when multiple <nav> elements exist.

Keyboard Interactions

TabMoves focus through interactive elements in DOM order: skip link, header, sidebar, main, footer.
Enter (on skip link)Jumps focus directly to the main content area.