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.
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:
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.
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:
https://github.com/picocss/picocss.com/assets/109556932/a3098d0e-70d4-4bfa-835d-bfb48d21aac4
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:
https://github.com/picocss/picocss.com/assets/109556932/acfad323-4a8f-4b15-b8f0-727ebb5812ea
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: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 justdark
. 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.