How to register global listener for window and add css variable with v-bind at nuxt pages/index

I am migrating my vue3 project to nuxt3, but I found that the main page at pages/index.vue is not the root page which also mounts when any page is active. In my vue project, I use app.vue to add dynamic css variable with v-bind and classes uses them and add global onresize eventHandler to window. So how can I let them run globally in nuxt as they did in my vue project? My vue solution is below.
onMounted(() => {
window.onresize = () => {
return (() => {
store.commit('windowInf/setDocumentBodySize', [document.body.clientWidth, Math.max(document.body.clientHeight, document.documentElement.clientHeight)])
})()
}
})
onMounted(() => {
window.onresize = () => {
return (() => {
store.commit('windowInf/setDocumentBodySize', [document.body.clientWidth, Math.max(document.body.clientHeight, document.documentElement.clientHeight)])
})()
}
})
.page{
--main-bg-color: v-bind('theme.list.mainColor');
--second-bg-color: v-bind('theme.list.secondColor');
--accent0-bg-color: v-bind('theme.list.accentColor[0]');
--accent1-bg-color: v-bind('theme.list.accentColor[1]');
--main-font-color: v-bind('theme.list.mainFontColor');
--second-font-color: v-bind('theme.list.secondFontColor');
--main-button-color: v-bind('theme.list.buttonColor');
--main-button-hover-color: v-bind('theme.list.buttonHoverColor');
background-color: var(--main-bg-color);
}
.page{
--main-bg-color: v-bind('theme.list.mainColor');
--second-bg-color: v-bind('theme.list.secondColor');
--accent0-bg-color: v-bind('theme.list.accentColor[0]');
--accent1-bg-color: v-bind('theme.list.accentColor[1]');
--main-font-color: v-bind('theme.list.mainFontColor');
--second-font-color: v-bind('theme.list.secondFontColor');
--main-button-color: v-bind('theme.list.buttonColor');
--main-button-hover-color: v-bind('theme.list.buttonHoverColor');
background-color: var(--main-bg-color);
}
3 Replies
kapa.ai
kapa.ai2mo ago
Hi @yukinoshita_sakura. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To implement global listeners and add CSS variables with v-bind in Nuxt 3, you can use a combination of the app.vue file and a client-side plugin. Here's how you can achieve this: 1. First, create an app.vue file in your project root if it doesn't exist already. This file serves as the main component that wraps all pages in Nuxt 3. You can add your CSS variables here:
<template>
<div class="page">
<NuxtPage />
</div>
</template>

<script setup>
import { useThemeStore } from '~/stores/theme'

const theme = useThemeStore()
</script>

<style>
.page {
--main-bg-color: v-bind('theme.list.mainColor');
--second-bg-color: v-bind('theme.list.secondColor');
--accent0-bg-color: v-bind('theme.list.accentColor[0]');
--accent1-bg-color: v-bind('theme.list.accentColor[1]');
--main-font-color: v-bind('theme.list.mainFontColor');
--second-font-color: v-bind('theme.list.secondFontColor');
--main-button-color: v-bind('theme.list.buttonColor');
--main-button-hover-color: v-bind('theme.list.buttonHoverColor');
background-color: var(--main-bg-color);
}
</style>
<template>
<div class="page">
<NuxtPage />
</div>
</template>

<script setup>
import { useThemeStore } from '~/stores/theme'

const theme = useThemeStore()
</script>

<style>
.page {
--main-bg-color: v-bind('theme.list.mainColor');
--second-bg-color: v-bind('theme.list.secondColor');
--accent0-bg-color: v-bind('theme.list.accentColor[0]');
--accent1-bg-color: v-bind('theme.list.accentColor[1]');
--main-font-color: v-bind('theme.list.mainFontColor');
--second-font-color: v-bind('theme.list.secondFontColor');
--main-button-color: v-bind('theme.list.buttonColor');
--main-button-hover-color: v-bind('theme.list.buttonHoverColor');
background-color: var(--main-bg-color);
}
</style>
2. To add a global window resize event listener, create a client-side plugin. Create a new file plugins/resize.client.ts:
export default defineNuxtPlugin((nuxtApp) => {
const store = useStore() // Replace with your actual store

const handleResize = () => {
store.commit('windowInf/setDocumentBodySize', [
document.body.clientWidth,
Math.max(document.body.clientHeight, document.documentElement.clientHeight)
])
}

if (process.client) {
window.addEventListener('resize', handleResize)
// Initial call
handleResize()
}

// Clean up the event listener when the app is unmounted
nuxtApp.hook('app:unmount', () => {
if (process.client) {
window.removeEventListener('resize', handleResize)
}
})
})
export default defineNuxtPlugin((nuxtApp) => {
const store = useStore() // Replace with your actual store

const handleResize = () => {
store.commit('windowInf/setDocumentBodySize', [
document.body.clientWidth,
Math.max(document.body.clientHeight, document.documentElement.clientHeight)
])
}

if (process.client) {
window.addEventListener('resize', handleResize)
// Initial call
handleResize()
}

// Clean up the event listener when the app is unmounted
nuxtApp.hook('app:unmount', () => {
if (process.client) {
window.removeEventListener('resize', handleResize)
}
})
})
This plugin will add the resize event listener when the app is mounted and remove it when the app is unmounted. 3. Make sure the plugin is registered in your nuxt.config.ts:
export default defineNuxtConfig({
// ... other configurations
plugins: [
'~/plugins/resize.client.ts'
]
})
export default defineNuxtConfig({
// ... other configurations
plugins: [
'~/plugins/resize.client.ts'
]
})
By implementing these steps, you'll have: 1. CSS variables with v-bind in the root component (app.vue) that will be available globally. 2. A global window resize event listener that updates your store. This approach leverages Nuxt 3's features to achieve the same functionality you had in your Vue 3 project. The app.vue file acts as the root component, and the client-side plugin ensures that the resize listener is added only on the client-side and properly cleaned up. Nuxt 3 Docs: App File Nuxt 3 Docs: Plugins ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@886243555411107862> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
yukinoshita_sakura
yukinoshita_sakuraOP2mo ago
I want to use global css variables with v-bind in company with nuxt pages(built-in vue-router and auto-generated router option).

Did you find this page helpful?