2021-10-11 12:57:54 +00:00
---
2022-10-06 09:15:30 +00:00
title: "layouts"
2022-11-21 15:51:39 +00:00
head.title: "layouts/"
2023-10-18 10:59:43 +00:00
description: "Nuxt provides a layouts framework to extract common UI patterns into reusable layouts."
2024-09-17 15:33:49 +00:00
navigation.icon: i-ph-folder
2021-10-11 12:57:54 +00:00
---
2021-06-08 21:44:30 +00:00
2024-09-17 15:33:49 +00:00
::tip{icon="i-ph-rocket-launch" color="gray" }
2023-10-18 10:59:43 +00:00
For best performance, components placed in this directory will be automatically loaded via asynchronous import when used.
::
2021-06-30 16:32:22 +00:00
2023-10-18 10:59:43 +00:00
## Enable Layouts
2021-06-30 16:32:22 +00:00
2023-10-18 10:59:43 +00:00
Layouts are enabled by adding [`<NuxtLayout>` ](/docs/api/components/nuxt-layout ) to your [`app.vue` ](/docs/guide/directory-structure/app ):
2021-06-30 16:32:22 +00:00
2023-10-18 10:59:43 +00:00
```vue [app.vue]
< template >
< NuxtLayout >
< NuxtPage / >
< / NuxtLayout >
< / template >
```
2021-06-30 16:32:22 +00:00
2023-10-18 10:59:43 +00:00
To use a layout:
2023-10-23 03:56:32 +00:00
- Set a `layout` property in your page with [definePageMeta ](/docs/api/utils/define-page-meta ).
2023-10-18 10:59:43 +00:00
- Set the `name` prop of `<NuxtLayout>` .
2024-02-21 17:09:45 +00:00
::note
2023-10-18 10:59:43 +00:00
The layout name is normalized to kebab-case, so `someLayout` becomes `some-layout` .
::
2024-02-21 17:09:45 +00:00
::note
2024-01-31 09:27:03 +00:00
If no layout is specified, `layouts/default.vue` will be used.
2023-10-18 10:59:43 +00:00
::
2024-02-21 17:09:45 +00:00
::important
2023-10-18 10:59:43 +00:00
If you only have a single layout in your application, we recommend using [`app.vue` ](/docs/guide/directory-structure/app ) instead.
::
2024-02-21 17:09:45 +00:00
::important
2022-04-07 10:59:40 +00:00
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 />` .
2022-03-14 10:47:24 +00:00
::
2023-10-18 10:59:43 +00:00
## Default Layout
2021-06-30 16:32:22 +00:00
2022-06-27 12:08:19 +00:00
Add a `~/layouts/default.vue` :
2021-06-30 16:32:22 +00:00
2022-06-27 12:08:19 +00:00
```vue [layouts/default.vue]
2021-06-30 16:32:22 +00:00
< template >
< div >
2023-10-18 10:59:43 +00:00
< p > Some default layout content shared across all pages< / p >
2021-06-30 16:32:22 +00:00
< slot / >
< / div >
< / template >
```
2023-10-18 10:59:43 +00:00
In a layout file, the content of the page will be displayed in the `<slot />` component.
2021-06-30 16:32:22 +00:00
2023-10-18 10:59:43 +00:00
## Named Layout
2022-06-27 12:08:19 +00:00
2023-10-18 10:59:43 +00:00
```bash [Directory Structure]
2022-03-14 10:47:24 +00:00
-| layouts/
2022-06-27 12:08:19 +00:00
---| default.vue
2022-03-14 10:47:24 +00:00
---| custom.vue
```
2023-10-18 10:59:43 +00:00
Then you can use the `custom` layout in your page:
2022-06-27 12:08:19 +00:00
2024-02-16 20:31:15 +00:00
```vue twoslash [pages/about.vue]
2023-07-18 10:31:45 +00:00
< script setup lang = "ts" >
2023-10-18 10:59:43 +00:00
definePageMeta({
layout: 'custom'
})
2023-07-18 10:31:45 +00:00
< / script >
2022-06-27 12:08:19 +00:00
```
2023-10-18 10:59:43 +00:00
::read-more{to="/docs/guide/directory-structure/pages#page-metadata"}
Learn more about `definePageMeta` .
::
2022-06-27 12:08:19 +00:00
2023-10-18 10:59:43 +00:00
You can directly override the default layout for all pages using the `name` property of [`<NuxtLayout>` ](/docs/api/components/nuxt-layout ):
2022-03-14 10:47:24 +00:00
2023-10-18 10:59:43 +00:00
```vue [app.vue]
< script setup lang = "ts" >
// You might choose this based on an API call or logged-in status
const layout = "custom";
2021-06-30 16:32:22 +00:00
< / script >
2022-05-31 22:34:41 +00:00
< template >
2023-10-18 10:59:43 +00:00
< NuxtLayout :name = "layout" >
2022-05-31 22:34:41 +00:00
< NuxtPage / >
< / NuxtLayout >
< / template >
```
2023-10-18 10:59:43 +00:00
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.
2022-04-25 16:54:20 +00:00
2023-10-18 10:59:43 +00:00
File | Layout Name
-- | --
`~/layouts/desktop/default.vue` | `desktop-default`
`~/layouts/desktop-base/base.vue` | `desktop-base`
`~/layouts/desktop/index.vue` | `desktop`
2021-10-21 10:14:40 +00:00
2023-10-18 10:59:43 +00:00
For clarity, we recommend that the layout's filename matches its name:
2022-04-25 16:54:20 +00:00
2023-10-18 10:59:43 +00:00
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"}
2022-06-08 19:53:39 +00:00
2022-08-13 07:27:04 +00:00
## Changing the Layout Dynamically
2021-10-21 10:14:40 +00:00
2023-10-18 10:59:43 +00:00
You can also use the [`setPageLayout` ](/docs/api/utils/set-page-layout ) helper to change the layout dynamically:
2021-10-21 10:14:40 +00:00
2024-02-16 20:31:15 +00:00
```vue twoslash
2023-07-18 10:31:45 +00:00
< script setup lang = "ts" >
2022-01-17 18:27:23 +00:00
function enableCustomLayout () {
2022-08-31 08:02:48 +00:00
setPageLayout('custom')
2022-01-17 18:27:23 +00:00
}
definePageMeta({
2022-01-26 11:56:24 +00:00
layout: false,
2022-01-17 18:27:23 +00:00
});
2021-10-21 10:14:40 +00:00
< / script >
2023-07-18 10:31:45 +00:00
< template >
< div >
< button @click =" enableCustomLayout " > Update layout</ button >
< / div >
< / template >
2021-10-21 10:14:40 +00:00
```
2022-04-09 09:25:13 +00:00
2023-10-18 10:59:43 +00:00
:link-example{to="/docs/examples/features/layouts"}
2022-06-27 12:08:19 +00:00
2022-08-13 07:27:04 +00:00
## Overriding a Layout on a Per-page Basis
2022-06-27 12:08:19 +00:00
2023-10-18 10:59:43 +00:00
If you are using pages, you can take full control by setting `layout: false` and then using the `<NuxtLayout>` component within the page.
2022-06-27 12:08:19 +00:00
::code-group
```vue [pages/index.vue]
2023-07-18 10:31:45 +00:00
< script setup lang = "ts" >
definePageMeta({
layout: false,
2023-10-18 10:59:43 +00:00
})
2023-07-18 10:31:45 +00:00
< / script >
2022-06-27 12:08:19 +00:00
< template >
< div >
< NuxtLayout name = "custom" >
< template #header > Some header template content. </ template >
The rest of the page
< / NuxtLayout >
< / div >
< / template >
```
```vue [layouts/custom.vue]
< template >
< div >
< header >
< slot name = "header" >
Default header content
< / slot >
< / header >
< main >
< slot / >
< / main >
< / div >
< / template >
```
::
2024-02-21 17:09:45 +00:00
::important
2023-10-18 10:59:43 +00:00
If you use `<NuxtLayout>` within your pages, make sure it is not the root element (or [disable layout/page transitions ](/docs/getting-started/transitions#disable-transitions )).
2023-10-16 21:58:40 +00:00
::