Skip to main content

Command Palette

Search for a command to run...

Prevent FOUC in astro

Updated
•3 min read•View as Markdown
Prevent FOUC in astro

When I am working on my own personal site(yes the one you are viewing now 🤣) using astro + tailwind plugin, I see a flashing on unstyled HTML. As I am using a free plan on netlify, the network latency makes the duration of the flash noticeably longšŸ¤¦ā€ā™‚ļø. To have a better UX, I have to find a way to solve it.

Root cause

Turns out the root cause is pretty simple:

  1. browser first loads the index.html

  2. after parsing the html, browser knows the site needs some additional .css files

  3. browser renders index.html

  4. browser fires css files request

  5. browser combines the .css and DOM to make the rendering styled

Clearly, the flash happens from step 3 to step 5.

General solution

To solve the flash of unstyled content(a.k.a. FOUC), various tricks can be used, but the general ideas are the same: hide the rendering in step 3 and only make it visible after step 5. Here, I will introduce the simplest method, which only requires CSS and no JS is needed.

The idea is like this:

  • Add an inline css rule in index.html with visibility: hidden;

  • In the separate css file, change the rule to visibility: visible;

Astro way to solve

To do this in astro, we can use the style directives. Add the following code in your root layout astro file:

<style is:inline>
  body {
    visibility: hidden;
    opacity: 0;
  }
</style>

<style is:global>
  body {
    visibility: visible;
    opacity: 1;
    transition: visibility 0.2s linear, opacity 0.2s linear;
  }
</style>

PS: Opacity in here is for transition, which makes the website a little bit smoother.

In the code snippet, all the css rules under is:inline will be bundled in the html file, and is:global will be extracted to a separate css file. This will make the browser renders html in hidden first, and then load the css file and our content gets visible.

Inline? Or not inline?

You may ask, why don't we put all the styles in is:inline?

The short answer is: I am using tailwind plugin and it compiles the style in css module so I have no choice.

The long answer is: you should not. If all our css goes into html file, the file will be very big, making it longer to download. If you modular our css files into chunks, the loading time can be reduced. Only containing critical css rules inline, and passing all the heavy massive rules to a separate file would be the optimal way in balancing both styling and UX.

Final words

As SPA + CSS in JS dominated the market for a while, this kind of ancient problem seems to be disappear for a while. As server side rendering starts to catch(or we should say re-catch) people's eyes, ancient problem returns. For me this is a very interesting experience, as most of the discussion related to FOUC are very old, but it works on the latest cutting-edge framework. It reminds me that knowledge is not depend on time. The Oldest thing doesn't mean outdated.

Hope you enjoy this article. šŸ˜„