El FOUC (Flash of Unstyled Content) és un dels problemes que més m’ha costat d’arreglar sempre. És un mal de cap. Ara, en aquest projecte em vaig trobar amb dos nivells de FOUC, i aquí explico com vaig solucionar tots dos.
Nivell 1: El Parpelleig de Color (The White Flash)
El navegador pinta la pàgina en blanc per defecte abans de carregar els teus estils foscos.
Solució: Injectar un script “bloquejant” al <head> del Layout principal.
Cal tenir en compte que això a més forma part de la lògica per controlar entre temes clar i fosc en iniciar el lloc.
<head>
<script is:inline>
(function() {
const theme = localStorage.getItem('theme');
const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (theme === 'dark' || (!theme && systemDark)) {
document.documentElement.classList.add('dark');
// Injecció directa d'estils per a immediatesa absoluta
document.documentElement.style.backgroundColor = '#131313';
document.documentElement.style.colorScheme = 'dark';
} else {
document.documentElement.classList.remove('dark');
document.documentElement.style.backgroundColor = '#ffffff';
document.documentElement.style.colorScheme = 'light';
}
})();
</script>
</head><head>
<script is:inline>
(function() {
const theme = localStorage.getItem('theme');
const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (theme === 'dark' || (!theme && systemDark)) {
document.documentElement.classList.add('dark');
// Injecció directa d'estils per a immediatesa absoluta
document.documentElement.style.backgroundColor = '#131313';
document.documentElement.style.colorScheme = 'dark';
} else {
document.documentElement.classList.remove('dark');
document.documentElement.style.backgroundColor = '#ffffff';
document.documentElement.style.colorScheme = 'light';
}
})();
</script>
</head>Nivell 2: El Salt de Layout (CSS Diferit)
Malgrat l’script, en navegar entre pàgines, els elements es “desmuntaven” per un instant.
El culpable: Un plugin d’optimització (@playform/inline) mal configurat.
Aquest plugin fa “inline” del CSS crític, però si es col·loca abans d’altres processos de build a astro.config.mjs, pot causar que el CSS es carregui de forma asíncrona incorrecta, provocant salts. O almenys això em va dir Gemini 3.
Solució:
Moure els plugins d’optimització al final de l’array integrations o… el que realment em va solucionar el problema, carregar-me’l.
export default defineConfig({
// MALAMENT: inline() abans de mdx()
// integrations: [tailwind(), react(), inline(), mdx()],
// BÉ: Optimitzacions al final (o deshabilitades si donen problemes)
integrations: [tailwind(), react(), mdx() /*, inline() */],
});export default defineConfig({
// MALAMENT: inline() abans de mdx()
// integrations: [tailwind(), react(), inline(), mdx()],
// BÉ: Optimitzacions al final (o deshabilitades si donen problemes)
integrations: [tailwind(), react(), mdx() /*, inline() */],
});Aquesta integració injecta CSS a l’HTML, hauria de servir per optimitzar la càrrega, però almenys en el meu cas va ser a costa d’afegir-me aquest FOUC. Per ara la seva eliminació no m’ha afectat en res aparent.
Lliçó: L’estabilitat visual (CLS) és més important que estalviar 2ms de càrrega. Si una optimització trenca l’experiència, fora.