Implementing Multiple Theme Support in NextJs

Vatsala Mittal
BYJU’S Exam Prep Engineering
5 min readMar 25, 2021

Switching between dark mode and light mode

Maximum approaches to implementing theme support are using the useDarkMode and ThemeProvider or Styled Components in Next.js. But what if there is a way to implement multiple themes without the need for extra libraries?

This approach will let us know how to implement the Dark Mode for Next.js. The fundamental strategy can also be used with any SSR app. Click HERE to see the DEMO for the implementation

Our requirements

Here’s our set of criteria for this feature

  • The user should be able to click a toggle to switch between Light and Dark mode.
  • The user’s preference should be saved, so that future visits use the correct color theme.
  • The site should not flicker on the first load, even if the user has selected a non-default color theme.

A workable solution

Here’s our solution, at a high level:

  • Use CSS variables for all of our stylings.
  • When we’re generating the HTML at compile-time, inject a <script> tag before all of our content (the page itself)
  • In that script tag, work out what the user’s color preferences are.
  • Update the CSS variables using JavaScript.

Getting Started

This implementation is done using the tutorial setup provided by nextJs

npx create-next-app nextjs-blog --use-npm --example "https://github.com/vercel/next-learn-starter/tree/master/learn-starter"

First, move all the styling in one folder naming /css and create a custom folder to add styling for custom modules with naming convention component-name.module.css.

Create a directory theme in the /css folder. Add two files: _light-color.css and _dark-color.css Below is the snippet that shows how to add colors in these files.

_dark-colors.css
_light-color.css
styles.css

Using the var feature of CSS we can dynamically add colors and create custom classes which will help in providing multiple themes to an application. So with this var variable when your theme changes the variable value changes according to the theme.

Implementation

The first step is to create a file theme-options.js in your components folder which would contain variables for all the themes you want on the website.

theme-options.js

Then we add a script that creates a minified version of our theme-colors which can be later used. Before running this script we create a directory /theme-css in our root so that the files can directly be added there.

Below is the script to minify our theme CSS. The file will be added to the root

write-theme-color.js

Create custom _app.js and _document.js files for this implementation.

The next step to achieve multi-theme is to create a cookie value name g-theme. This will let us know what type of theme we need our website to look at. In _app.js of the application add the following code snippet in the Main Component.

In _document.js we create a themeMap that stores minified files for both light and dark colors. We pass the theme map in our Initial Props.

In our render function of _document.js, we find out which theme is currently active.

Here as you can see we are storing the value in themeCss by accessing data from themeMap that are accessed from props that were added above.

Once you have data in themeCss we add a style tag in the body in _document.js and return the following code snippet

Note : To avoid Automatic Static Optimization by Next js make sure to add getInitialProps in your _app.js. And if you have static page then try using Incremental Static Regeneration

Now, all we need to do is create a button component that changes the theme-mode for the application. Import the component wherever the toggle button is needed. On click of the button, the setCookieValue(Custom function that adds cookies) function will be called and would set the value for cookie g-theme opposite of the currently set value.

dark-mode.js

Deployment

  1. After all the files have been added and changed for themes. We will first run write-theme-colors.js. Add the command to run the script in package.json.
  2. First, delete your node_modules and .next folder. The install the node modules again and create a production build.
  3. After the production build is created. We start the server and run the write-theme-color.js script parallelly. Once the files have been created stop the server.
  4. We start the server again and click on the button for switching to dark-mode. The page would reload and you will see the themeCss is embedded in the body tag is changed and colors have changed to values defined in _dark-mode.css.

To check out the source code for the implementation click HERE and for the demo click HERE.

--

--