0

I am developing a static website. I am appending CSS style-sheet to document head using JavaScript. After CSS loads I do some calculations based on position and dimensions of elements. So it is mandatory for CSS to load first and then calculate.

But the problem is that Chrome browser waits for script to execute and while it appends stylesheet to head but doesn't actually download it, and hence document.stylesheets does not update!

This problem is only with chrome. Firefox downloads it instantly as expected!

I have created a sample code to easily demonstrate the problem

<!DOCTYPE html>
<head></head>
<body>
    <p id='status'></p>
    <button onclick="updateStatus()">updateStatus</button>
    <script>
        const link = document.createElement('link')
        link.rel = 'stylesheet'
        link.href = './style.css'
        document.head.appendChild(link)
        updateStatus()
        function updateStatus() {
            document.getElementById('status').innerHTML = document.styleSheets.length;
        }
        </script>
</body>
</html>

Try opening this question in chrome and Firefox. If you run snippet in Chrome it will increment by one, means the CSS is loaded later. On the other hand, Firefox value does not change means it has loaded CSS first.

How can I force chrome or any other browser to load CSS first and then continue JavaScript execution?

I have tried attaching onload event (also suggested here) to stylesheet and it works, but my code is large and multipurpose. I can't split it into pre-CSS and post-CSS parts!

Ankur Parihar
  • 458
  • 6
  • 16

4 Answers4

0

A simple fix when it comes to this kind of problem is to convert the files to .PHP and host them locally using wampserver or similar service :)

The reason that chrome does not update is that the style is kept in the cache. By developing in PHP you'll force the browser to refresh the styling every time.

At least this is the way I solve it.

Eric Qvarnström
  • 779
  • 6
  • 21
  • I think you misinterpreted question. The problem here is not about cache refresh. Chrome puts CSS file on hold until JavaScript finishes. But I want it to download immediately. – Ankur Parihar Jun 21 '20 at 02:45
0

You may be looking for an obscure hack to detect when a link element has loaded its content.

Unfortunately, there is no "load" event for links; for example the following callback never runs:

let link = document.createElement('link');
link.href = '...';
link.addEventListener('load', () => { /* ... */ });

Someone clever realized that img elements, on the other hand, do offer a "load" event - therefore if it was an img tag loading your stylesheet resource instead of a link tag, you would be able to see the event.

The only extra knowledge we need at this point to get this hack working is to understand that if an img tag loads a resource that cannot be interpreted as an image, it will throw an "error" event instead of a "load" event.

So the following code should, oddly, let you detect when the resource identified by your link's href is loaded:

let link = document.createElement('link');
link.rel = '...';
link.href = '...';

let imgForDetectingLoad = document.createElement('img');
imgForDetectingLoad.src = link.href; // Load the same resource
imgForDetectingLoad.addEventListener('error', () => {
  // The `link` element has loaded its content!
});
Gershom Maes
  • 7,358
  • 2
  • 35
  • 55
  • `onload` works fine on link. Here: https://jsfiddle.net/1bdjxo9w/1/ . But any event on `img` or `link` is not a problem at all! `load` or `error` will only work after the resource has been downloaded! But the problem is that Chrome is blocking resource download! That's the problem. – Ankur Parihar Jun 21 '20 at 03:53
  • Your jsfiddle has a bug - should be `img.onload = () => console.log('...')`, not `img.onload = console.log('...')` (which immediately evaluates `console.log`) – Gershom Maes Jun 21 '20 at 05:10
  • Noted! My bad (⌣́_⌣̀) – Ankur Parihar Jun 21 '20 at 05:23
0

Just use a random number in url. This will prevent browser from loading your stylesheet from cache.

link.href = './style.css?rand=' + Math.random(); 

Hope this would help you

0

As I get it, you just want to load the CSS first and therefore always get a value of 1, because you load one CSS - which, by the way, does not exist and creates a 404 :)

So just use setTimeout to give the browser the chance to finish the script, set the CSS information and then continue with your updateStatus method:

setTimeout(updateStatus, 0);