4.3 KiB
title | head.title | description | navigation.icon |
---|---|---|---|
layouts | layouts/ | Nuxt provides a layouts framework to extract common UI patterns into reusable layouts. | i-ph-folder-duotone |
::callout{icon="i-ph-rocket-launch-duotone"} For best performance, components placed in this directory will be automatically loaded via asynchronous import when used. ::
Enable Layouts
Layouts are enabled by adding <NuxtLayout>
to your app.vue
:
<template>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</template>
To use a layout:
- Set a
layout
property in your page with definePageMeta. - Set the
name
prop of<NuxtLayout>
.
::callout{color="blue" icon="i-ph-info-duotone"}
The layout name is normalized to kebab-case, so someLayout
becomes some-layout
.
::
::callout{color="blue" icon="i-ph-info-duotone"}
If no layout is specified, layouts/default.vue
will be used.
::
::callout{icon="i-ph-lightbulb-duotone"}
If you only have a single layout in your application, we recommend using app.vue
instead.
::
::callout{color="amber" icon="i-ph-warning-duotone"}
Unlike other components, your layouts must have a single root element to allow Nuxt to apply transitions between layout changes - and this root element cannot be a <slot />
.
::
Default Layout
Add a ~/layouts/default.vue
:
<template>
<div>
<p>Some default layout content shared across all pages</p>
<slot />
</div>
</template>
In a layout file, the content of the page will be displayed in the <slot />
component.
Named Layout
-| layouts/
---| default.vue
---| custom.vue
Then you can use the custom
layout in your page:
<script setup lang="ts">
definePageMeta({
layout: 'custom'
})
</script>
::read-more{to="/docs/guide/directory-structure/pages#page-metadata"}
Learn more about definePageMeta
.
::
You can directly override the default layout for all pages using the name
property of <NuxtLayout>
:
<script setup lang="ts">
// You might choose this based on an API call or logged-in status
const layout = "custom";
</script>
<template>
<NuxtLayout :name="layout">
<NuxtPage />
</NuxtLayout>
</template>
If you have a layout in nested directories, the layout's name will be based on its own path directory and filename, with duplicate segments being removed.
File | Layout Name |
---|---|
~/layouts/desktop/default.vue |
desktop-default |
~/layouts/desktop-base/base.vue |
desktop-base |
~/layouts/desktop/index.vue |
desktop |
For clarity, we recommend that the layout's filename matches its name:
File | Layout Name |
---|---|
~/layouts/desktop/DesktopDefault.vue |
desktop-default |
~/layouts/desktop-base/DesktopBase.vue |
desktop-base |
~/layouts/desktop/Desktop.vue |
desktop |
:link-example{to="/docs/examples/features/layouts"}
Changing the Layout Dynamically
You can also use the setPageLayout
helper to change the layout dynamically:
<script setup lang="ts">
function enableCustomLayout () {
setPageLayout('custom')
}
definePageMeta({
layout: false,
});
</script>
<template>
<div>
<button @click="enableCustomLayout">Update layout</button>
</div>
</template>
:link-example{to="/docs/examples/features/layouts"}
Overriding a Layout on a Per-page Basis
If you are using pages, you can take full control by setting layout: false
and then using the <NuxtLayout>
component within the page.
::code-group
<script setup lang="ts">
definePageMeta({
layout: false,
})
</script>
<template>
<div>
<NuxtLayout name="custom">
<template #header> Some header template content. </template>
The rest of the page
</NuxtLayout>
</div>
</template>
<template>
<div>
<header>
<slot name="header">
Default header content
</slot>
</header>
<main>
<slot />
</main>
</div>
</template>
::
::callout
If you use <NuxtLayout>
within your pages, make sure it is not the root element (or disable layout/page transitions).
::