·
2 min read

Vue Tip: Dynamically Change Page Title

Vue Tip: Dynamically Change Page Title Image

To set the document title, we define the <title> tag in our index.html file:

index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <link rel="icon" href="/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Vue Tip: Dynamically Change Page Title</title> </head> <body> <div id="app"></div> <script type="module" src="/src/main.js"></script> </body> </html>

In many applications, we have different routes and want to show a dedicated title for each route.

Unfortunately, this does not work out of the box, and we need to write some code to enable this functionality.

Let's take a look at an exemplary route configuration (check the Vue Router docs for more details about Vue Router):

router.js
import { createRouter, createWebHistory } from 'vue-router' import Home from '@/views/Home.vue' const router = createRouter({ history: createWebHistory(), routes: [ { path: '/', component: Home, }, { path: '/about', component: () => import('@/views/About.vue'), }, { path: '/contact', component: () => import('@/views/Contact.vue'), }, ], }) export default router

We can use the beforeEach guard on the router instance to dynamically set the document title on each route. The beforeEach guard adds a navigation guard that executes before any navigation:

router.js
router.beforeEach((to, from) => { document.title = to.meta?.title ?? 'Default Title' })

Warning

In this example, we edit the page title using the document object, which is not advised when using server-side rendering (SSR). I recommend the vue-meta package if you are looking for an SSR-friendly solution. It offers a more adaptable and universal approach to handling page metadata in a Vue application.

Inside the navigation guard callback, we use document.title to set the document's title. We use the nullish coalescing operator (??) in combination with optional chaining (?.) to set Default Title if the meta object or the title is undefined.

Finally, we need to define the metadata on our routes:

router.js
routes: [ { path: '/', component: Home, meta: { title: 'Home', }, }, { path: '/about', component: () => import('@/views/About.vue'), meta: { title: 'About', }, }, { path: '/contact', component: () => import('@/views/Contact.vue'), meta: { title: 'Contact', }, }, ],

At this point, we have updated our code to dynamically update the page title when the page changes. The following StackBlitz playground contains a running example:

We can improve the code by adding "more dynamic" page titles using route props:

ClientLink.vue
<script setup> const client = await useClient() </script> <template> <router-link :to="{ name: 'ViewClient', params: { pageTitle: `${client.firstName} ${client.lastName}` } }"> View client details </router-link> </template>

We can access the route params via to.params and set the document's title accordingly:

router.js
router.beforeEach((to, from, next) => { const titleFromParams = to.params?.pageTitle if (titleFromParams) { document.title = `${titleFromParams} - ${document.title}` } else { document.title = to.meta?.title ?? 'Default Title' } })

If you liked this Vue tip, follow me on X to get notified about new tips, blog posts, and more. Alternatively (or additionally), you can subscribe to my weekly Vue & Nuxt newsletter:

I will never share any of your personal data. You can unsubscribe at any time.