Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Light/Dark mode FOUC on all pages #16

Open
FireIsGood opened this issue Mar 25, 2024 · 0 comments
Open

Light/Dark mode FOUC on all pages #16

FireIsGood opened this issue Mar 25, 2024 · 0 comments

Comments

@FireIsGood
Copy link

Currently, there is a Flash of Unstyled Content on all pages when the user has the color scheme opposite to their browser preference—prefers light with dark mode or prefers dark with light mode.

This is seen where the browser flashes dark/light before correcting itself.

Example:

Peek.2024-03-25.05-10.mp4

To fix this, you would need to somehow set the HTML attribute before the page is loaded. As posted in a related issue in the examples repository, this can be solved with an inlined script checking the user's preference and/or localstorage theme selection in the head tag.

I am not skilled at Remix styling, however I have made a quick patch fix to show what this could look like:

Peek.2024-03-25.05-19.mp4

The specific code for this is VERY hacky, however it may be helpful for making a better implementation. The following code was placed in /app/components/Head.jsx at the bottom of the <head> tag:

      <script
        dangerouslySetInnerHTML={{
          __html: `
// This must be inline to stop FOUC

const localStorageKey = "picoColorScheme";
const rootAttribute = "data-theme";

const scheme = (() => {
  // Check for a stored theme
  if (typeof localStorage !== "undefined" && localStorage.getItem(localStorageKey) !== undefined) {
    return localStorage.getItem(localStorageKey);
  }

  // Otherwise, check the user's color scheme preference
  return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
})();

// Set a data attribute for Pico
document.querySelector("html")?.setAttribute(rootAttribute, scheme.split('"').at(1));
`,
        }}
      ></script>

A better solution is likely using something like the <Script> functionality to somehow get type safe code pasted into the head before the page loads, however I am not experienced in either React or Remix specifically.

Additionally, the script has to do weird things like scheme.split('"').at(1) since the existing local storage is set to the string of "dark" instead of just dark. I'm not sure if this is to help with the theme changer or JSX as a whole, but this caused a weird bug when I was trying to run the code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant