Dark Mode with Tailwind CSS and Next.js
Posted at 24/01/2021
Last updated at 14/05/2023
This quick little piece is to help you implement, in a very streamlined fashion, a dark mode toggle in your website using Tailwind CSS and Next.js.
Before getting it down, I was battling my brain out at trying to set up this, especially given Next.js's server-side rendering stuff. Because of that, I was having trouble using the usual
local.storage method for saving the preferred theme on the browser's cache. I naturally got a little overwhelmed as it seemed like a much harder task than I could've ever hoped for.
But after researching all articles around and asking for help late at night from my dev friends, I got to a very, very, simple setup using these two frameworks.
Setting up the stack
It all goes down to this library. And it does what it says: "perfect dark mode in 2 lines of code". Easy peasy. Just install it on your project using any of these two:
Once it is installed, go to the
_app.js file on your project, which is automatically created after installing Next, and just wrap all of the elements of the
MyApp component with the
ThemeProvider, just like so:
First, make sure to properly install Tailwind by following their guide tailored focused on a Next.js project. Once that's done, go to your
tailwind.config.js file and change the dark mode property to class, just like that:
Now, go back to the
_app.js file and just add as an attribute to the ThemeProvider a class value:
Creating the theme toggle button
With everything set up, we now need to create the button that will be responsible for toggling dark mode on and off. I promise you it's not super complex! Let's start by creating a
DarkModeButton.js file in your components folder (create one if you don't have one yet).
We'll use React hooks to add functionality. These will be basically responsible for toggling the
dark class, mounting the theme as a whole, and also toggling the icons that we'll add within the button.
Your component should now be looking like this. Make sure you remember to import everything correctly!
Now comes the fun part of actually designing the button! Don't forget to add the
dark: prefix to classes that are targeting the dark mode. For example, feel free to start with the styles I've added to my button.
Note that I went ahead and already added the
aria-label attribute, which is important for accessibility (making the screen readers' lives easier when reading the page's elements).
Getting closer to the end, add the
onClick event to your button element and pass the function that will objectively toggle your theme, using the
setTheme hook we created.
Lastly, we'll now insert a sun and moon icon inside the button so the user knows which theme they'll get by clicking on it. To do that, we'll add an SVG element and use the
theme conditionals to toggle just the
path element, depending on the mode. Use whatever icons you want for this, though!
mounted hook is set to false by default, meaning your website will initially render in light mode. To change that, just swap it to true instead.
Woof, that's it! ⚡️🎚🎉
You should now have a functioning dark mode toggle button on your website/app. This is a particularly cool implementation as it avoids a common pitfall with dark mode out there: the annoying flashy-ness. Tailwind also makes tailoring your design for dark mode super easy. It's tough to have neat 1:1 light and dark mode color scale mapping, and sometimes you need special treatment to preserve the interface's depth & hierarchy.
I hope this wasn't too hard to follow and that it helped you solve something that took me literally freaking weeks to figure out. Enjoy! 🤙
Be aware of hydration mismatches
If you're seeing this lil tutorial and have recently updated to the latest Next.js version (> 13.0), make sure to follow these instructions to avoid any hydration mismatches between what's on the client and on the server while using theme ternaries to toggle dark & light modes.