Theme-ui: Conditional render on colorMode makes components flash

Created on 15 May 2020  路  3Comments  路  Source: system-ui/theme-ui

Hi! So on my gatsby-website, I render a dark-light mode icon, rendering conditionally if the current color scheme is dark or default.

{colorMode === "default" ? <Dark /> : <Light />}

When I refresh the page in dark mode color scheme, a very brief flash of changing components can be seen. I don't have this issue with other context items, or when I'm refreshing in the default scheme. This works:

{genderState.gender === 1 ? <Female /> : <Male />}

I can't seem to find a solution to this, not even in the docs. I also tried to disable prefers-color-scheme and localStorage. Please feel free to immediately close this issue if this isn't a bug.

EDIT: when logging colorMode, the two modes get logged. So default is active before dark.

Most helpful comment

Because Gatsby sites are prerendered on the server side, they cannot detect a user's browser's setting (e.g. localStorage) until the client-side JS bundle rehydrates. The color modes feature uses CSS custom properties and a render-blocking script to avoid this visual effect for colors rendered by Theme UI, but colorMode will change after rehydration if the user has set it to a non-default value. I'm unsure how you're handling the genderState example in your site, but for Theme UI's color mode state, it won't be able to prevent a flash based on switching components, if that makes sense.

Instead of a ternary for different components, you might be able to handle this in a more "Theme UI way", e.g. something like <Icon sx={{ color: 'text' }} />, which would use the same mechanism for applying styles that everything else styled with Theme UI uses

All 3 comments

Because Gatsby sites are prerendered on the server side, they cannot detect a user's browser's setting (e.g. localStorage) until the client-side JS bundle rehydrates. The color modes feature uses CSS custom properties and a render-blocking script to avoid this visual effect for colors rendered by Theme UI, but colorMode will change after rehydration if the user has set it to a non-default value. I'm unsure how you're handling the genderState example in your site, but for Theme UI's color mode state, it won't be able to prevent a flash based on switching components, if that makes sense.

Instead of a ternary for different components, you might be able to handle this in a more "Theme UI way", e.g. something like <Icon sx={{ color: 'text' }} />, which would use the same mechanism for applying styles that everything else styled with Theme UI uses

I understand, thank you for your explanation. I guess that is one of the limitations of using a SSR framework. I'll try to work around this issue!

<Icon sx={{ color: 'text' }} />
This won't work though, as I'm conditionally using an other svg, depending on the colorMode. But again, this isn't that much of a problem, and you explained it well. Thanks for the help!

Yeah, sorry if that option doesn't work for your use-case -- if you come up with a better way to handle that, please let us know. For now, I'm going to close this out, since I can't think of any clear next steps

Was this page helpful?
0 / 5 - 0 ratings