tailwind dark mode isn't extending fully when scrolling all the way on page

Viewed 229

using dark mode in a nextjs web app with tailwind, when scrolling, if you scroll past the scroll container (almost like your bouncing off the bottom or top of the page when scrolling), the dark mode isn't extending all the way, so the color isn't applying and it's just the previous color underneath (white in this case), what is the reason for this and is there a way to extend the dark mode fully?

Browsers that don't work

  • Firefox
  • Brave
  • Chrome

Browsers that do work

  • Safari

stackoverflow and tailwindcss.com in dark mode handle this well and the dark mode extends fully on the whole page

_app.tsx

 <Store state={state} dispatch={dispatch}>
        <Head>
          <meta charSet="UTF-8" />
          <meta
            name="viewport"
            content="width=device-width, initial-scale=1.0"
          />
        </Head>
        <div className="h-screen dark dark:bg-black dark:text-white overscroll-auto lg:overscroll-contain">
          <Component {...pageProps} id="app" />
        </div>
      </Store>{" "}
4 Answers

You must apply the styles to the body or :root (HTML) element. For the examples, I'll show them applied to the :root element.

You have two primary options in Next.js - global stylesheet or inline.

Global stylesheet with tailwind directives

Global styles

global.css

@tailwind base;

@layer base {
 :root {
  @apply dark:bg-black dark:text-white;
 }
}

inline class

To apply styles inline, you must create a custom _document page. Again, you can apply the styles to either the body or html tags.

_document.js

import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
  return (
    <Html className="dark:bg-black dark:text-white">
      <Head />
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

I believe you need to add these classes to the <body> of the document, not just the main div.

There are a few ways to do add css classes to the body in NextJS, but one of the more common ways is to add it in a useEffect or componentDidMount of your Layout component depending on what kind it is.

For example:

useEffect(() => {
  document.querySelector("body").classList.add("dark dark:bg-black dark:text-white");
}, []);

I was running into the same problem. Turns out it was because my dark background/foreground color styling was on a React component (a container layout component) rather than being on the body element.

I fixed it by setting the dark background/foreground directly on the body element in my css file:

@layer base {
  body {
   @apply dark:bg-slate-800 dark:text-white;
  }
}

Then in your pages/_app.jsx file or wherever, you can call document.documentElement.classList.add("dark"); and the dark mode will be set properly even on scroll.

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

I tried all of previous answers and none of them worked for me. The only thing that finally worked was to create a _document.js, and add an id to the HTML section:

_document.js

import React from 'react'
import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
    return (
        <Html id="html" className="bg-white">
            <Head />
            <body className="bg-bg-light dark:bg-bg-dark">
                <Main />
                <NextScript />
            </body>
        </Html>
    )
}

Then add and remove the dark background (without the 'dark:' prefix) during the toggle:

DarkMode.jsx

useEffect(() => {

    if (darkMode !== undefined) {
        if (darkMode) {
            document.body.classList.add("dark");
            document.getElementById("html").classList.add("bg-black")
        } else if (!darkMode) {
            document.body.classList.remove("dark");
            document.getElementById("html").classList.remove("bg-black")
        }
    }
}, [darkMode])

I did not add the tailwind directive to globals.css

Thanks to Sean W for setting me in the right direction.

Related