skip to content

CSS Themes In Astro and FART issue

How to avoid FART issue in Astro projects and build a cool, light and easy to set-up CSS themes changer.

Cover

Why am I here?

  • I want to remove my flickering theme issue
  • I want to understand basic of FART issue
  • I want a cool and easy CSS theme changer with 29 pre-defined themes (BONUS)

Why my theme switcher bug in Astro

Astro is a static site generator, by default everything is HTML processed, optimized, bundled before served to the browser.

Theme flickering is most of the time due by the browser builds the page’s DOM tree before he got the theme value.

Flash of inAccurate coloR Theme

In General, theme data is stored in the localStorage of your browser when user select his preferred theme.

 // This need to be executed before html rendering
if (localStorage.getItem("theme") === null) {
document.documentElement.setAttribute("data-theme", "light");
} else
document.documentElement.setAttribute("data-theme", localStorage.getItem("theme"));
}

The JavaScript used to grab the saved theme has to be executed before any DOM content loaded, or you will face a lovely Flash of inAccurate coloR Theme issue ! 🙃

For more information about FART, CodePen Co-founder Chris Coyier made a nice article on it.

Astro is:inline directive

Astro is:inline permit to avoid process, optimize, or bundle for <style/> or <script/> contents.

The trick is to use the previous <script/> in the <head/> of your Astro page to be sure it will be executed before any HTML rendering.

<!-- src/layouts/MyWrapperGlobalLayout.astro -->
<html lang="en">
  <head>
    <script is:inline>
      if (localStorage.getItem("theme") === null) {
        document.documentElement.setAttribute("data-theme", "light");
      } else
        document.documentElement.setAttribute(
          "data-theme",
          localStorage.getItem("theme") 
        );
    </.script>
    <meta charset="utf-8" />
    <title>My Cool Astro Layout Wrapping All My Pages</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
  </head>
  <body>
    <nav>
      <a href="#">Home</a>
      <a href="#">Posts</a>
      <a href="#">Contact</a>
    </nav>
    <article>
      <slot /> <!-- Your content from src/pages is injected here -->
    </article>
  </body>
</html>

Notice that I'm using an Astro Layout here to include all the pages of my Astro sites.


--- Bonus ---

To create your CSS theme changer, we will use theme-changer and daysiUI, a TailwindCSS framework offering 29 pre-defined CSS themes.

# use pnpm, npm or yarn
pnpm i daisyui && pnpm i theme-change
// tailwind.config.js
module.exports = {

// add daisyUI plugin
plugins: [require("daisyui")],

// add daisyUI themes
daisyui: {
themes: ["light", "dark", "cupcake", "bumblebee", "emerald", "corporate", "synthwave", "retro", "cyberpunk", "valentine", "halloween", "garden", "forest", "aqua", "lofi", "pastel", "fantasy", "wireframe", "black", "luxury", "dracula", "cmyk", "autumn", "business", "acid", "lemonade", "night", "coffee", "winter"],
},
}
}

In addition, daysiUI offer a very cool theme generator!

Next, we can add our previous localStorage logic in your Wrapper Layout or any astro page you want.

<!-- src/layouts/MyWrapperGlobalLayout.astro -->

---

<html data-theme="dark">
  <head>
    <script is:inline>
      if (localStorage.getItem("theme") === null) {
        document.documentElement.setAttribute("data-theme", "dark");
      } else
        document.documentElement.setAttribute(
          "data-theme",
          localStorage.getItem("theme")
        );
    </script>
    <script>
      import { themeChange } from "theme-change";
      themeChange();
    </script>
  </head>
  <slot /> <!-- Your content from src/pages is injected here -->
</html>

To finish, add data-set-theme="theme you want" on any clickable HTML element and your theme will be applied.

<!-- src/layouts/page.astro -->

---

<button data-set-theme="cupcake" data-act-class="outline">
	 Cupcake theme
</button>

To conclude this first post, I made a sweet demo based on what we learn and inspired by the daisyUI documentation made by Pouya Saadeghi, creator of daisyUI and theme-changer.

A cool result
Buy Me A Coffee