Build a multi-theme website using Nuxt.js, TailwindCSS and DaisyUI

Cover image Photo by Tim Arterbury

In this tutorial, you will learn how to create a multiple theme website with Nuxt.js 2, TailwindCSS, and DaisyUI. You will learn how to use and set up DaisyUI in your Nuxt project, how to add multiple themes to your project using DaisyUI's pre-built themes and how to create your own theme.

Preview of what we will be creating: Image

If you prefer to dive right in to the code, you can check out the code for this tutorial:


Let's have a quick review of DaisyUI before proceeding to our tutorial.

What is DaisyUI?

DaisyUI is a TailwindCSS plugin created by Pouya Saadeghi. It composes of highly customizable and themeable HTML component classes that can be applied to your HTML.

Say for example you have a card component that you want to use in your project. Instead of designing your card component like this

<div class="rounded-md border-2 shadow-md bg-black-700">
	card content
</div>

you can use DaisyUI classes to make it look like this

<div class="card">
	card content
</div>

DaisyUI also injects a set of semantic color names to Tailwind. So instead of using generic color names like bg-blue-{}, you can use semantic role names like bg-primary or bg-success.

Say for example you want to create a button component with different styles, e.g a primary or secondary button or maybe a link button, you can apply DaisyUI's semantic classes to style the component.

<button class="btn btn-primary">
	Primary Button
</button>

<button class="btn btn-secondary">
	Secondary Button
</button>

<button class="btn btn-link">
	Link Button
</button>

Check out DaisyUI's documentation for more information about available classes and component samples.


Let's build our website

Create a Nuxt project

First up, create a fresh Nuxt project and choose TailwindCSS as UI framework.

yarn create nuxt-app <project-name>
or
npx create-nuxt-app <project-name>

Image

This creates a new project with TailwindCSS installed. We need to use tailwind.config.js, to create that, run the following command

npx tailwindcss init

We can now use TailwindCSS classes in our Nuxt project.

Set up DaisyUI

Next, install DaisyUI.

yarn add daisyui
or
npm install daisyui

Open tailwind.config.js and add DaisyUI.

module.exports = {

  ...

  plugins: [
    require('daisyui'),
  ],
  daisyui: {
    themes: [
      'light', // first one will be the default theme
      'luxury',
      'dark',
    ],
  },
}

We define the themes we will use in our project. For this tutorial, we'll use DaisyUI's prebuilt themes - light, luxury, and dark themes.

DaisyUI has ready-to-use prebuilt themes. We'll use some of them for demonstration purposes. Check out DaisyUI's https://daisy.ui.com/ to see the complete list of available themes.

We are now ready to use DaisyUI components classes and themes.

Create a header and sample pages

Let's create a simple header for our site. We'll display a dropdown list of themes here and links to sample pages. We will add two sample pages - index (default page) and about page.

Create a TheHeader.vue inside src/components folder and paste the following code:

<template>
 <div class="flex justify-between">
  <div class="px-2 mx-4">
   <div class="hidden lg:flex">
    <nuxt-link to="/" class="btn btn-ghost btn-sm rounded-btn">
     Home
    </nuxt-link>
    <nuxt-link to="/routines" class="btn btn-ghost btn-sm rounded-btn">
     About
    </nuxt-link>
   </div>
  </div>
 </div>
</template>

<style scoped>
.nuxt-link-exact-active {
 @apply bg-yellow-500 text-black;
}
</style>

Then import it in the default layout. Inside root project directory, create a layout folder, and inside that folder create a file called default.vue and paste the following code:

// layouts/default.vue

<template>
 <div>
  <TheHeader />
  <Nuxt />
 </div>
</template>
<script>
import TheHeader from '@/components/TheHeader'

export default {
 components: { TheHeader },
}
</script>

If you want to automatically add components without importing, use the nuxt/components library.

Inside index.vue page, paste the following code:

<template>
	<div class="flex mx-auto w-full">
		<h1 class="text-6xl font-bold">INDEX PAGE</h1>
	</div>
</template>

and the about.vue page

<template>
	<div class="flex mx-auto w-full">
		<h1 class="text-6xl font-bold">ABOUT PAGE</h1>
	</div>
</template>

Select component

Next, we will create a select component. We'll use this for choosing our theme.

Inside the components folder, create SelectTheme.vue and paste the following code:

  <template>
    <select class="select select-bordered w-full max-w-xs">
    <option disabled="disabled" selected="selected">Choose your theme</option>
    <option v-for="(theme, index) in themes" :key="index">{{ theme }}</option>
  </select>
  </template>

  <script>
  export default {
    data(){
      return {
        themes: [
          'light',
          'luxury',
          'dark',
        ]
      }
    }
  }
  </script>

This creates a simple select component using DaisyUI's classes. We then create an array of themes selection: luxury, light, dark themes.

Then import this component in the TheHeader component.

// TheHeader.vue

<template>
 <div class="flex justify-between">
  <div class="px-2 mx-4">
   <div class="hidden lg:flex">
    <nuxt-link to="/" class="btn btn-ghost btn-sm rounded-btn">
     Home
    </nuxt-link>
    <nuxt-link to="/about" class="btn btn-ghost btn-sm rounded-btn">
     About
    </nuxt-link>
        <!-- IMPORT COMPONENT HERE -->
        <SelectTheme />
   </div>
  </div>
 </div>
</template>
<script>
  import SelectTheme from '@/components/SelectTheme.vue'
  export default {
    components: {
      SelectTheme
    }
  }
</script>
<style scoped>
.nuxt-link-exact-active {
  @apply bg-yellow-500 text-black;
}
</style>

Choosing the theme

We've created our SelectTheme component. Now we need to create its functionality. We need to listen whenever the user switches the theme and then store the value of the theme in localStorage. For this we'll use theme-change library. So let's install it first.

Install theme-change

npm install --save theme-change
or
yarn add theme-change

Now we can use theme-change.

Remove everything from the SelectTheme component, and paste the following code.

<template>
 <div>
  <select
   v-model="key"
   class="select select-bordered select-sm"
   data-choose-theme
  >
   <option v-for="(theme, index) in themes" :key="index" class="mr-5">
    {{ theme }}
   </option>
  </select>
 </div>
</template>

<script>
import { themeChange } from 'theme-change'

export default {
 data() {
  return {
   themes: ['light', 'luxury', 'dark'],
   key: '',
  }
 },

 async mounted() {
  themeChange(false)
  await this.getTheme()
 },

 methods: {
  getTheme() {
   this.key = localStorage.getItem('theme') || 'dark
   return this.key
  },
 },
}
</script>

Our SelectTheme component is now ready to use.

Listen to changes in theme

To use the DaisyUI theme, we need to add the data-theme="THEME_NAME" attribute in our HTML tag. Nuxt has no index.html by default, so how can we add data-theme to our app? The solution is to overwrite the .nuxt/views/app.template.html and write our app.html.

Inside our root project folder, create app.html, and paste the following code.

// app.html
<!DOCTYPE html>
<html {{ HTML_ATTRS }} data-theme"light">
 <head {{ HEAD_ATTRS }}>
  {{ HEAD }}
 </head>
 <body {{ BODY_ATTRS }}>
  {{ APP }}
 </body>
</html>

We just copy the content from .nuxt/views/app.template.html and append the data-theme="light" attribute. We define light theme by default.

Or if you don't want the above solution, you can set the data-theme attribute inside the app layout. Paste the following code:

// layouts/default.vue

<template>
 <div data-theme="light">
  <TheHeader />
  <Nuxt />
 </div>
</template>
<script>

import TheHeader from '@/components/TheHeader'

export default {
 components: { TheHeader },
}
</script>

Either way, both solutions work.

Now run the project and point your browser to localhost:3000.

That's it. You now have a working multi-theme Nuxt app.

Adding your own theme

To add your own theme, you define custom theme inside tailwind.config.js and then add it to the daisyui's themes array.

daisyui: {
	themes: [
		{
			mytheme: {
				/* your theme name */
				primary: "#a991f7" /* Primary color */,
				"primary-focus": "#8462f4" /* Primary color - focused */,
				"primary-content":
					"#ffffff" /* Foreground content color to use on primary color */,

				secondary: "#f6d860" /* Secondary color */,
				"secondary-focus": "#f3cc30" /* Secondary color - focused */,
				"secondary-content":
					"#ffffff" /* Foreground content color to use on secondary color */,
			},
		},
	];
}

Next

Fix Vue package mismatch error