Environment: client, and server if ssr: true
Local
Cumulative
Provided by: vike-react/vike-vue/vike-solid

You need vike-react/vike-vue/vike-solid to be able to use the +Layout setting. If you don't use vike-{react,vue,solid} then see Without vike-{react,vue,solid}.

What are layouts?

Pages usually share a common layout, like a shared header, sidebar, and footer. The +Layout setting lets you define such shared layout.

You can also define multiple layouts: some pages can share one layout, while other pages share a different one. For example, admin and marketing pages typically have different layouts.

The component defined by the +Layout setting wraps the component defined by +Page.

<Layout>     ⟸ component defined by +Layout
  <Page />   ⟸ component defined by +Page
</Layout>

To define a global layout applying to all your pages:

// /pages/+Layout.tsx
 
export { Layout }
 
import React from 'react'
 
// `children` includes the +Page component (and all inner +Layout components)
function Layout({ children }: { children: React.ReactNode }) {
  return <>
    <Navigation/>
    <Content>{children}</Content>
  </>
}
function Navigation() { /* ... */ }
function Content() { /* ... */ }

Don't forget to use children (or <slot> if you use Vue).

See API > Config Files > Inheritance for an explanation of why /pages/+Layout.jsx applies to all pages.

If you're adding a wrapper component required for installing a tool, we recommend using <Wrapper> instead.

Multiple

You can define several layouts that apply to different groups of pages.

# Marketing pages share a layout
pages/(marketing)/+Layout.js
pages/(marketing)/index/+Page.js    # URL: /
pages/(marketing)/about/+Page.js    # URL: /about
 
# Admin pages share another layout
pages/admin-panel/+Layout.js
pages/admin-panel/index/+Page.js    # URL: /admin-panel
pages/admin-panel/users/+Page.js    # URL: /admin-panel/users

The directory (marketing) is skipped by Filesystem Routing, see Guides > Routing > Filesystem Routing.

You can use .clear.js and .default.js to control the inheritance chain.

See also: API > Config Files > Inheritance

Nested

You can define layouts that nest into each other:

# Global outer layout that applies to all pages
pages/+Layout.js
# Inner layout nested into the global outer layout, for marketing pages
pages/(marketing)/+Layout.js
# Inner layout nested into the global outer layout, for admin pages
pages/admin-panel/+Layout.js

Here pages/+Layout.js applies to all pages, including the marketing and admin pages.

The Layout setting is cumulative: pages/(marketing)/+Layout.js doesn't override pages/+Layout.js. Instead, the <Layout> components nest within each other:

<Layout>      ⟸ pages/+Layout.js
  <Layout>    ⟸ pages/(marketing)/+Layout.js
    <Page />  ⟸ pages/(marketing)/about-us/+Page.js
  </Layout>
</Layout>

You can use .clear.js and .default.js to control the inheritance chain.

You can also implement same-page navigations such as tabs:

/product/42/pricing                   /product/42/reviews
+------------------+                  +-----------------+
| Macbook          |                  | Macbook         |
| ...              |                  | ...             |
| +--------------+ |                  | +-------------+ |
| | Pricing      | |  +------------>  | | Reviews     | |
| | ...          | |                  | | ...         | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+
pages/+Layout.js                      # Global layout (shared among all pages)
pages/product/@id/+Layout.js          # Outer content ("Macbook" ...)
pages/product/@id/pricing/+Page.js    # Inner content ("Pricing" ...)
pages/product/@id/reviews/+Page.js    # Inner content ("Reviews" ...)

If your nested layout isn't associated with a URL (if the pricing and reviews tabs share the same URL /product/42) then you can use a stateful component instead of <Layout>.

To avoid the page scrolling to the top, make sure to use:

Examples:

Data fetching

To fetch data for your layouts see:

pageContext

You can access the pageContext object by using usePageContext().

// /pages/+Layout.tsx
 
export { Layout }
 
import React from 'react'
import { usePageContext } from 'vike-react/usePageContext' // or vike-{vue,solid}
 
function Layout({ children }: { children: React.ReactNode }) {
  const pageContext = usePageContext()
  // ...
}

Without vike-{react,vue,solid}

The following is for users that don't use a UI framework Vike extension vike-react/vike-vue/vike-solid.

The simple way

A simple way to implement layouts is to manually wrap your <Page> components:

// /pages/index/+Page.tsx
 
export { Page }
 
import { LayoutDefault } from '../layouts/LayoutDefault'
 
function Page() {
  return <>
    <LayoutDefault>
      {/* ... */}
    </LayoutDefault>
  </>
}
// /pages/admin/+Page.tsx
 
export { Page }
 
import { LayoutDashboard } from '../layouts/LayoutDashboard'
 
function Page() {
  return <>
    <LayoutDashboard>
      {/* ... */}
    </LayoutDashboard>
  </>
}

With a custom setting

You can implement the Layout setting yourself by using meta.

Examples:

Nested Layout

See the Nested section above. For smooth nested layout navigation, we recommend using Client Routing. (Using Server Routing leads to full page reloads which usually isn't acceptable for same-page navigations.)

See also