javascripthtmlcssfouc

How to deal with FOUC while implementing style switch


I'm implementing a theme switcher with JavaScript and saving the theme in the cookie as the answer here: CSS Stylesheet Switching via adding cookies, but I'm struggling with FOUC while switching between pages now.

I found some answers that don't work for me.

1. There is a solution where this can be resolved by adding new CSS that will be loaded before the whole HTML, but since I have 3 CSS (for example - 3 different backgrounds) for 3 themes I don't think it is the solution for me because I can't have 3 dynamic backgrounds in that new CSS that will be overridden after loading the whole HTML. Am I in right?

2. I tried with rel="stylesheet preload"... as="style" and rel="preload"... as="style" In order to load the whole CSS before HTML but that just not doing anything

3. I have also tried to load CSS before HTML by inserting this script in the head

<script> 
function show(){
document.getElementById('wrapper').style.visibility = 'visible';
} 
</script>

and put id="wrapper" in body like this:

<body>
        <div id="wrapper" class="d-none d-sm-block d-md-none d-lg-none d-xl-none d-xxl-none"> ...etc

and still no progress with FOUC

Here is the part of my code:

  1. JavaScript in an external file:
window.onload = function () {
    var viewmode = getCookie("viewmode");
    if (viewmode)
        document.getElementById('swap').setAttribute('href', viewmode);
};

function swapStylesheet(sheet) {
    document.getElementById('swap').setAttribute('href', sheet);
    setCookie("viewmode", sheet, 30);
}

function setCookie(name, value, days) {
    var d = new Date();
    d.setTime(d.getTime() + days * 24 * 60 * 60 * 1000);
    document.cookie = name + "=" + value + "; expires=" + d.toUTCString() + "; path=/";
}

function getCookie(name) {
    var cookies = document.cookie.split(";");
    for (var i = 0; i < cookies.length; i++)
    {
        var ck = cookies[i].trim().split("=");
        if (ck[0] === name)
            return ck[1];
    }
    return false;
}

CSS imports in every HTML head:

        <link rel="stylesheet" type="text/css" href="/css/style.css">
        <link rel="stylesheet" id="swap" type="text/css" href="/css/theme-dark.css">
        <link rel="stylesheet" type="text/css" href="/css/calendar.css">

Buttons for theme switch

<div class="dropdown-container ms-4">
    <button onClick="swapStylesheet('/css/theme/theme-dark.css')">[[#{dashboard.theme-dark}]]</button>
    <button onClick="swapStylesheet('/css/theme/theme-light.css')">[[#{dashboard.theme-light}]]</button>
    <button onClick="swapStylesheet('/css/theme/theme-blue.css')">[[#{dashboard.theme-blue}]]</button>
</div>

I don't know so much JavaScript and this is the first time I'm using cookies. Maybe this is not a big problem but right now I'm stuck here...


Solution

  • After deleting the window.onload function the problem is gone.