Environment: client, and server if ssr: true
Cumulative: true
Global: false

Provided by: vike-react/vike-vue/vike-solid

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

What are layouts?

Pages usually share a common visual design. The +Layout setting enables you to define such shared visual appearance.

You can also define multiple designs: some pages can share a design while other pages share another one. (For example, admin pages and marketing pages typically have a different design.)

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

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

If you want to add a wrapper component that is required for installing a tool, then we generally recommend using <Wrapper> instead.

Global

You can define a layout that applies to all your pages:

// /pages/+Layout.jsx
 
export { Layout }
 
// `children` includes <Page>
function Layout({ children }) {
  return <>
    <Navigation/>
    <Content>{children}</Content>
  </>
}
function Navigation() { /* ... */ }
function Content() { /* ... */ }

The reason /pages/+Layout.jsx applies to all pages is explained at API > Config Files > Inheritance.

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

See API > Config Files > Inheritance.

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

Setting a default <Layout> that is overridable isn't currently supported, see #1692 - Add override and default options for cumulative configs.

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 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.jsx
 
import { usePageContext } from 'vike-react/usePageContext' // or vike-{vue,solid}
 
export function Layout({ children }) {
  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.js
 
export { Page }
 
import { LayoutDefault } from '../layouts/LayoutDefault'
 
function Page() {
  return <>
    <LayoutDefault>
      {/* ... */}
    </LayoutDefault>
  </>
}
// /pages/admin/+Page.js
 
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

OSZAR »