The problem ¶
This Hugo theme I wrote have had a problem. It defaults to the light mode, but if you switch to the dark mode1, then when loading a new page it will first render the light mode and then automatically switch to the dark, looks like it flashes white a little bit. I thought all the static sites have to face this problem, until one day I found some healthy themes, for instance, PaperMod⧉. So, there must be a way to solve this.
I searched this on the internet. There is an article Fix the White Flash on Page Load When Using a Dark Theme on a Static Site⧉ by the maintainer of theme Cupper⧉. I tried their solution. In Chrome, it indeed works; but in Firefox it doesn’t. Firefox will render visibility: hidden; opacity: 0;
to a whole blank page, and only after DOMContentLoaded
happens showContent()
function will show the content. Means: the page still flashes. Before it flashes the light mode, now it flashes the blank page. Just as bad as before.
I think the difference between Firefox and Chrome is because the developers of Chrome used magic, they tried their best to bring Chrome users a better experience. And this covers up the real problem for the Hugo theme developers who use Chrome.
Find the cause ¶
The main idea is still to understand the process of how the browser render a page. Simply put:
- You request for a page;
- The browser download the entire HTML and save as DOM, then parse and render the page from top to bottom;
- Stop parsing when encountering an external CSS or JavaScript file. Download it and then continue;
- When encountering
<style></style>
or just loaded external styles, store them as CSSOM and re-render the influential part; - When encountering
<script></script>
or just loaded external scripts, stop parsing and run the scripts. Continue parsing and rendering after finish running them; - So on and so on until all the works are done.
The cause to the white flash problem is that I put the JavaScript for theme’s mode switching at the end of <body>
, like this:
|
|
The solution ¶
The solution to this problem is quite simple, with two points:
- Put the script for theme’s mode switching into
<head>
, in order to determine the theme currently selected by the user before rendering the body;
- Put the script for theme’s mode switching into
- Upgrade the container for the theme to the entire
<html>
, i.e., from
- Upgrade the container for the theme to the entire
|
|
to
|
|
This is because <body>
has not been rendered at this time, and the only object that can be manipulated by the script in <head>
is <html>
.
Now the problem is completely solved, the complete code is as follows:
|
|
The approach to dark mode in this theme is CSS variable, see this tutorial⧉ for reference. ↩︎
See also
- No.1: Fix the White Flash on Page Load When Using a Dark Mode on a Static Site - Build a Theme (This one!)
- No.2: Make Hugo Invert Color for Images when Using a Dark Mode - Build a Theme