As I wrote yesterday, I celebrated John Siracusa’s every-five-year Hypercritical t-shirt sale with a new Hypercritical Gold Theme for this site. As with my previous dark/light mode configuration, toggling themes is done with a little icon button at the bottom of the menu that can look like a sun (when in light mode), a moon (when in dark mode), and now a 128k Mac (when in Hypercritical Gold mode).
Theme toggling can cause flickering issues when pages load. The symptom is that when you click a link to go to another page on the site, you see a flash of the wrong colors and then the page quickly switches to your chosen theme colors. This is because when the default colors load first, and then the browser realizes you’ve set the theme to something else and loads the correct colors. I had this issue myself, but I didn’t really notice it when I just had light/dark modes, probably because I was almost always in dark mode. I did notice it right away when I added Hypercritical Gold.
I found two articles addressing this issue, one of which was even written from an Astro perspective.
They both basically use exactly the same technique – early on in the page, either in the
<head> section or early in the
localStorage setting for your theme choice is.
As it happens, I was already doing this. But I was doing it in my menu component, which in turn is called by my Base.astro base layout. Also my script was declared as
<script> instead of
<script is:inline>, which in Astro means it was getting bundled by Vite instead of loading directly inline where it was declared. The result of these two factors meant the timing of the script checking the visitor’s theme preference was off, and theme flicker was the result.
My first attempt at getting rid of theme flicker was changing the script to use the
To recap, I no longer have a
Menu.astro component. My menu is now in my
The moral of the story is, grab the user theme preference and set the theme early in the page load lifecycle. With Astro, that means understanding how Astro is optimizing your layouts, components, CSS, and scripts.