Application using TailwindCSS cannot change to light mode if system is set to dark mode

2.4k views Asked by At

I am working on a new project using the T3 stack, and I want to be able to toggle from light and dark mode. However, only the text colour changes, and the background is always set to the system's preferences.

If I set the browser theme to light, then the background is light, and if I set the browser theme to dark, then the background is dark. While either is set, I toggle light and dark theme within the Web app and the text colour changes, but the background remains the same.

Is there a specific class I need to set to some element, other than what is described in the documentation, in order for the theme to properly switch between light and dark?

In other words, are bg-base-100 and bg-base-content, etc. CSS classes that are dynamically set to the proper colours, or do I have to explicitly set the colours of every elements in my app?

Edit

This is a representation side-by-side between Google Chrome (left) and Firefox (right) of the exact same site. The background changes because I have added bg-slate-100 text-slate-800 dark:bg-slate-800 dark:text-slate-100 to the content container element.

Note how the toolbar (i.e. navbar bg-neutral text-neutral-content) and the table (i.e. table table-compact) do not change background color, but the text color is correctly applied.

Light mode Dark mode

2

There are 2 answers

0
Yanick Rochon On BEST ANSWER

My theme switching function was like the one found in the documentation, that is :

function applyTheme() {
  if (typeof window !== "undefined") {
    if (
      localStorage.theme === "dark" ||
      (!("theme" in localStorage) &&
        window.matchMedia("(prefers-color-scheme: dark)").matches)
    ) {
      document.documentElement.classList.add("dark");
    } else {
      document.documentElement.classList.remove("dark");
    }
  }
}

However, I am using DaisyUI, so I missed this part :

<html data-theme="cupcake"></html>

In other words, the data-theme HTML attribute. Modifying my applyTheme function to :

function applyTheme() {
  if (typeof window !== "undefined") {
    if (
      localStorage.theme === "dark" ||
      (!("theme" in localStorage) &&
        window.matchMedia("(prefers-color-scheme: dark)").matches)
    ) {
      document.documentElement.classList.add("dark");
      document.documentElement.setAttribute("data-theme", "dark");
    } else {
      document.documentElement.classList.remove("dark");
      document.documentElement.setAttribute("data-theme", "light");
    }
  }
}

Makes it work.

3
erff-on On

You need to have a button in your UI with a click event listener that adds or removes a dark class to your components.

sample code :

// On page load or when changing themes, best to add inline in `head` to 

avoid FOUC
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
  document.documentElement.classList.add('dark')
} else {
  document.documentElement.classList.remove('dark')
}

// Whenever the user explicitly chooses light mode
localStorage.theme = 'light'

// Whenever the user explicitly chooses dark mode
localStorage.theme = 'dark'

// Whenever the user explicitly chooses to respect the OS preference
localStorage.removeItem('theme')

documentation link : https://tailwindcss.com/docs/dark-mode