DEV Community

ultroNeous Technologies
ultroNeous Technologies

Posted on

Creating Multiple Themes in Tailwind CSS and Next.js

Tailwind CSS has gained immense popularity for its utility-first approach to styling, enabling developers to quickly build modern and responsive user interfaces. When combined with a powerful framework like Next.js, you have a winning combination for building dynamic and performant web applications. In this tutorial, we'll explore how to create multiple themes using Tailwind CSS and integrate them seamlessly into a Next.js project.

Step 1: Setting Up Your Next.js Project:

To begin, open your terminal and enter the following command to create a new Next.js project using the latest version:



npx create-next-app@latest


Enter fullscreen mode Exit fullscreen mode

Image description
Once the project generation is complete, navigate into the newly created project directory by running:



cd my-app


Enter fullscreen mode Exit fullscreen mode

Step 2: Creating Multiple Theme Variants:

In your project's source directory, navigate to the styles folder and open the global.css file and set up your base Tailwind CSS configuration:



@tailwind base;
@tailwind components;
@tailwind utilities;

/* Your base theme settings */
@layer base {
  html {
  --color-primary: #4285f4;
  --color-secondary: #34a853;
  --color-buttons: #fbbc05;
  --color-typography: #ea4335;
  }
}


Enter fullscreen mode Exit fullscreen mode

Create a folder named themes inside the styles directory.

Inside the themes folder, create individual CSS files for each theme variant: theme1.css, theme2.css, and theme3.css

Customise each theme variant's color palette, typography, and other design attributes within their respective CSS files.

src/styles/themes/theme1.css



html[data-theme="theme1"] {
--color-primary: #f98866;
--color-secondary: #80bd9e;
--color-buttons: #89da59;
--color-typography: #ff320e;
}


src/styles/themes/theme2.css
html[data-theme="theme2"] {
--color-primary: #f4cc70;
--color-secondary: #6ab187;
--color-buttons: #de7a22;
--color-typography: #20948b;
}


Enter fullscreen mode Exit fullscreen mode

src/styles/themes/theme3.css



html[data-theme="theme3"] {
--color-primary: #f1f1f2;
--color-secondary: #a1d6e2;
--color-buttons: #bcbabe;
--color-typography: #1995ad;
}


Enter fullscreen mode Exit fullscreen mode

In global.css Below your base theme settings, you can start importing your theme variants.



@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
html {
--color-primary: #4285f4;
--color-secondary: #34a853;
--color-buttons: #fbbc05;
--color-typography: #ea4335;
}
@import "themes/theme1.css";
@import "themes/theme2.css";
@import "themes/theme3.css";
}


Enter fullscreen mode Exit fullscreen mode

Step 3 : setting up tailwind Configuration

Open the tailwind.config.js file and configure it to extend the theme colors using the CSS custom properties defined in your global.css

Tailwind.config.ts



module.exports = {
    content: [
      './src/pages/**/*.{js,ts,jsx,tsx,mdx}',
      './src/components/**/*.{js,ts,jsx,tsx,mdx}',
      './src/app/**/*.{js,ts,jsx,tsx,mdx}',
    ],
    theme: {
      extend: {
        colors: {
          primary: 'var(--color-primary)',
          secondary: 'var(--color-secondary)',
          buttons: 'var(--color-buttons)',
          typography: 'var(--color-typography)',
        },
      },
    },
    plugins: [],
  };


Enter fullscreen mode Exit fullscreen mode

This configuration tells Tailwind CSS to use the CSS custom properties (variables) defined in your global.css for the extended theme colors.

By adding this tailwind.config.js file, you're ensuring that your Tailwind styles align with the custom theme colors you've defined. This setup will help you maintain consistency throughout your application while easily switching between different themes.

Step 4: Dynamic Theme Switching

Inside your project directory, create a folder named utils if it doesn't exist, and then create a file named helper.ts within it.

In the helper.ts file, define a function called changeTheme that takes a theme string as an argument and applies it as a data attribute to the HTML element:

src/utils/helper.ts



export const changeTheme = (theme: string) => {
  document.querySelector("html")?.setAttribute("data-theme", theme);
};


Enter fullscreen mode Exit fullscreen mode

In your src/pages/index.tsx file (or another appropriate component), import the changeTheme function.

Inside your component, create buttons that, when clicked, call the changeTheme function with the corresponding theme name:

src/pages/index.tsx



import { changeTheme } from "@/utils/helper";

export default function Home() {
  return (
   <div className='h-screen grid place-items-center bg-primary'>
    <div>
      <button className='py-2 px-8 bg-buttons text-typography m-2' onClick={() => changeTheme("")}>Default</button>
      <button className='py-2 px-8 bg-buttons text-typography m-2' onClick={() => changeTheme("theme1")}>theme 1</button>
      <button className='py-2 px-8 bg-buttons text-typography m-2' onClick={() => changeTheme("theme2")}>theme 2</button>
      <button className='py-2 px-8 bg-buttons text-typography m-2' onClick={() => changeTheme("theme3")}>theme 3</button>
    </div>
   </div>
  )
}


Enter fullscreen mode Exit fullscreen mode

By implementing this code, you're creating a dynamic theme switching mechanism that allows users to switch between different themes by clicking the corresponding buttons. The changeTheme function sets the data-theme attribute on the HTML element, which is then used by your custom theme variants in the global.css and tailwind.config.js files to apply the correct styling.

Conclusion:

In this tutorial, you've learned how to create and switch between multiple themes in your Tailwind CSS and Next.js projects. Starting from setting up your Next.js app using the latest version, you customize themes using CSS variables in global.css. By extending the Tailwind theme in the configuration file, you ensured consistency.

The implementation of dynamic theme switching was achieved through the changeTheme function in helper.ts. Integrating theme-switching buttons in your components, as shown in the example index.tsx, allows users to instantly transform the app's appearance.

Mastering this skill equips you to cater to diverse user preferences, enhancing the user experience and showcasing your app's adaptability. With the ability to offer various themes at the click of a button, you're ready to create engaging and user-centric web applications.

Congratulations on mastering the art of multiple themes with Tailwind CSS and Next.js. Enjoy creating captivating user interfaces and delivering exceptional experiences!

Top comments (6)

Collapse
 
barrymichaeldoyle profile image
Barry Michael Doyle

Hmmm, this seems to be missing something. I folllowed all your steps and got:

Error: Event handlers cannot be passed to Client Component props.
button className=... onClick={function} children=...
^^^^^^^^^^^^^^
If you need interactivity, consider converting part of this to a Client Component.

Collapse
 
cke profile image
Christian Koch Echeverria

Simply adding "use-client" at the beginning of the page.
But I think you might need a nextjs basic guide if this error message confused you.

Collapse
 
barrymichaeldoyle profile image
Barry Michael Doyle

Well nah, it's more like I assumed and expected this solution would work for app router. I understand the error, the part that confuses me is why the tutorial doesn't mention this.

Collapse
 
jsgitrepo profile image
Jake

Looks like this guide is for pages router, not app router. I think that means it would translate to client components in app router but not server components.

Collapse
 
kemora_13conf profile image
Abdelghani El Mouak

This is such a clever and innovative approach to managing multiple themes in Tailwind CSS and Next.js! The way you used CSS variables and Tailwind's configuration is not only smart but also super practical for real-world projects. Thanks for sharing such valuable insightsβ€”this is definitely going to help many developers streamline their theming process!

Collapse
 
didoshakra profile image
Roman

Everything works perfectly. Thank you!