Vue Tip: Dynamically Change Page Title


To set the document title, we define the <title>
tag in our index.html
file:
<!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):
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.beforeEach((to, from) => { document.title = to.meta?.title ?? 'Default Title'})
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:
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:
<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.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 Twitter to get notified about new tips, blog posts, and more. Alternatively (or additionally), you can subscribe to my weekly Vue newsletter.