import { Link, RepoLink } from '@brillout/docpress' import { UiFrameworkVikeExtension, ImplementedBy } from '../../components'
Layout
setting
What are layouts? Pages can have different layouts: for example, if admin panel pages (
/admin/product/@id
and/admin/user/@id
) have a sidebar while marketing pages (/
and/about-us
) have a sticky header instead. The admin pages can share the same<Layout>
component that includes the sidebar, while the marketing pages can share the<Layout>
component that includes the sticky header.
The Layout
setting wraps your Page component with another component (the layout component).
<Layout> ⟸ component defined by the setting "Layout"
<Page /> ⟸ component defined by the setting "Page"
</Layout>
You can apply a layout as default to all pages:
// /pages/+Layout.js
// This layout component is the default layout
export { Layout }
// ...
See also: .
You can then override the default layout on a page-by-page basis:
// pages/product/@id/+Layout.js
// This layout component overrides the default layout and
// applies to the product page /product/@id
export { Layout }
// ...
You can also define a layout for a group of pages:
// /pages/admin/+Layout.js
/* This layout applies only to admin pages (/pages/admin/**) such as:
URL FILESYSTEM
/admin /pages/admin/+Page.js
/admin/user/@id /pages/admin/user/@id/+Page.js
/admin/product/@id /pages/admin/product/@id/+Page.js
*/
export { Layout }
// ...
See also
<Wrapper>
which also wraps<Page>
, but for different use cases.
What are nested layouts? A nested layout is, essentially, when a page has a route with multiple parameters. For example
/product/@id/@view
:URL id view ===================== ==== ======= /product/1337 1337 null /product/1337/pricing 1337 pricing /product/42/reviews 42 reviews
/product/42/pricing /product/42/reviews +------------------+ +-----------------+ | Product | | Product | | +--------------+ | | +-------------+ | | | Pricing | | +------------> | | Reviews | | | | | | | | | | | +--------------+ | | +-------------+ | +------------------+ +-----------------+
If your nested layout isn't associated with a URL (in other words the pricing page and the reviews page share the same URL
/product/42
), then you can simply use a stateful component instead of the following.
You can implement a nested layout by using a route with multiple parameters:
// /pages/product/+route.js
export default '/product/@id/@view'
You can also use a Route Function for full programmatic flexibility, see this example.
To ensure @view
matches a list of pre-defined values, you can use a guard()
hook with throw render(404)
:
// /pages/product/+guard.js
import { render } from 'vike/abort'
export function guard(pageContext) {
const { view } = pageContext.routeParams
if (!['reviews', 'pricing'].includes(view)) {
throw render(404)
}
}
You can then use pageContext.routeParams.view
to implement the nested layout:
// /pages/product/+Page.js
export { Page }
import { usePageContext } from 'vike-react/usePageContext' // or 'vike-vue' / 'vike-solid'
function Page() {
const pageContext = usePageContext()
const nestedLayout = (() => {
const { view } = pageContext.routeParams
if (view === 'reviews') return <Reviews />
if (view === 'pricing') return <Pricing />
})()
return <>
{/* ... */}
{/* Somewhere deep */ }
{ nestedLayout }
{/* ... */}
</>
}
Finally, make sure to use <a href="/product/42/reviews" keep-scroll-position />
(and navigate('/product/42/reviews', { keepScrollPosition: true })
) to avoid the browser to scroll to the top.
Once #1459 - Nested Routes is implemented, Vike will automatically preserve the scroll position.
Examples:
- - [Nested Layout implementation](https://github.com/vikejs/vike/blob/main/examples/layouts-react/pages/starship/%2BPage.jsx)
- - [Nested Layout implementation](https://github.com/vikejs/vike/blob/main/examples/layouts-vue/pages/starship/%2BPage.vue)
The following is for users that don't use a .
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>
</>
}
In case you don't use a , you can implement the Layout
setting yourself by using meta.
Examples:
See .
For smooth nested layout navigation, we recommend using Client Routing. (Using Server Routing leads to full page reloads upon nested layout navigation which usually isn't an acceptable UX.)