-
Notifications
You must be signed in to change notification settings - Fork 30
Description
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.