ryne

ryne

github

nuxt + useDark dark mode flashing issue

Problem#

Every time the page refreshes, there is a flash, for example, setting black refresh initially to white, then it changes back to black.

Reason#

useDark is stored in local storage by default, and it cannot access local storage in SSR state.

Handling#

// nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      script: [
        {
          innerHTML: `
            (function() {
              const isDark = localStorage.getItem('darkMode') === 'true' || 
                (!localStorage.getItem('darkMode') && window.matchMedia('(prefers-color-scheme: dark)').matches);
              document.documentElement.classList.toggle('dark', isDark);
            })();
          `,
          type: 'text/javascript',
        },
      ],
    },
  },
})

Subsequent Issue#

Hydration class mismatch

Reason#

Although the flash issue has been resolved, the initialized value of useDark during SSR is still an incorrect value (unable to access local storage).

Solution#

Use session to store

const isDark = useDark({
    storageKey: 'vueuse-color-scheme',
    storage: {
      getItem(key: string) {
        if (import.meta.server) {
          // Server-side gets cookie from headers
          const cookieStr = useRequestHeaders(['cookie'])?.cookie || ''
          return cookieStr.split('; ').find(row => row.startsWith(key))?.split('=')[1] || null
        }
        return document.cookie.split('; ').find(row => row.startsWith(key))?.split('=')[1] || null
      },
      setItem(key: string, value: string) {
        document.cookie = `${key}=${value};path=/;max-age=${60 * 60 * 24 * 30}`
      },
    } as Storage,
  })
// nuxt.config.ts
script: [
        {
          innerHTML: `
            (function() {
              var getCookie = function(name) {
                return document.cookie.split('; ').find(row => row.startsWith(name))?.split('=')[1] || null;
              };
              var darkMode = getCookie('vueuse-color-scheme');
              if (darkMode === 'dark') {
                document.documentElement.classList.add('dark');
              } else {
                document.documentElement.classList.remove('dark');
              }
            })();
          `,
          type: 'text/javascript',
        },
      ],
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.