0

I am using the following code to reload a stylesheet when the user makes a selection:

<link type="text/css" id="main_style" href="css/style.php" rel="stylesheet">

<button id="secret_1" style="display:none;"></button>

$(document).ready(function(){
function freshStyle(stylesheet){
   $('#main_style').attr('href',stylesheet);
}
$('#secret_1').click(function(event){
    event.preventDefault();
    var restyled = 'style.php?v='+Math.floor(Math.random() * 10000); 
    freshStyle(restyled);
});
});

In Chrome, the reload happens fluidly, and the transitions look great. In Firefox, the website temporarily becomes a garbled mess (while the stylesheet is being reloaded) for a second before the new stylesheet is active.

Is this something that can be solved with code, or is this just a feature of the Firefox browser?

Joe
  • 143
  • 10
  • I'd try adding the new stylesheet and then removing the old, I think the "feature" as you call it is because firefox is more efficient at redrawing the page, so, actually redraws between the presence of the old and new stylesheet – Bravo May 17 '22 at 01:37
  • @Bravo corrected the use of Math.random. The thing is that I'm using a partly-dynamically created stylesheet with PHP, so users can change elements on the fly. I suppose, worst-case scenario, I could just use some form of fade background with high opacity to block what's going on in the background. – Joe May 17 '22 at 02:27
  • Or you could try what I suggested – Bravo May 17 '22 at 02:57
  • One thing to note though, the load event on a link rel=stylesheet fires just before the style is actually applied - so, I would further delay the deletion of the existing stylesheet using a setTimeout of 0 ms – Bravo May 17 '22 at 03:15

1 Answers1

0

If you load the new stylesheet and remove the old one once the new takes effect, the flash of unstyled format should no longer happen

Note: I've done away with jquery inside the .ready since I don't really know how to do a lot of what is happening here in jQuery - vanilla JS all the way for me (but you can convert to jquery if you're more comfortable with it)

$(document).ready(function() {
    function freshStyle(stylesheet) {
        const id = 'main_style';
        const main = document.getElementById(id);
        const sibling = main.nextElementSibling;
        const parent = main.parentElement;
        
        const style = document.createElement('link');
        style.rel = 'stylesheet';
        style.href = stylesheet;

        style.onload = () => {
            // load fires BEFORE style is applied - so delay a tick
            setTimeout(() => {
                // remove the old stylesheet
                main.remove();
                // set the id of the new sheet to the removed one
                style.id = id;
            }, 0);
        };
        // this just ensures the new stylesheet ends up exactly where the old was
        parent.insertBefore(style, sibling);
    }
    document.getElementById('secret_1').addEventListener('click', (e) => {
        e.preventDefault();
        const restyled = `style.php?v=${Math.floor(Math.random() * 10000)}`; 
        freshStyle(restyled);
    });
});
Bravo
  • 6,022
  • 1
  • 10
  • 15
  • I tried this, but go the following error "Uncaught DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node." – Joe May 17 '22 at 03:25
  • I fixed it. It was because this is in Wordpress and the "head" needs to be added via a function, instead of just on the plugin page itself. And your fix does indeed work. Thank you so much! – Joe May 17 '22 at 03:48
  • Oh @Joe - I assumed `` elements are in `` – Bravo May 17 '22 at 03:50
  • @Joe - I've changed the code so it should work regardless of where the `` element is – Bravo May 17 '22 at 03:51
  • The new one is even more convenient because now I can keep the stylesheet in my plugin main page, which is easier for me... as I make a lot of plugins, and prefer to have access to the files (opposed to going back and forth). Thanks again for your help, seriously. This is going to make for a significantly better user experience. – Joe May 17 '22 at 03:59