If the problem is really bad internet, refreshing the page is clearly not a good idea, because internet will still be bad when you refresh and chances are you'll just lose the few elements that have already loaded and you'll end up with a self-resetting, never-ending loop.
Let's break down what happens when a page loads:
<head> is read entirely, and no javascript is executed before CSSOM is built
CSSOM is built, after all CSS resources in it are read/loaded and parsed
<body> is added to DOM and, in parallel, the browser starts:
- executing
javascript, in order, starting with the scripts in <head> followed by the ones in <body> (if any)
- reading/building
DOM, queuing up all external resources for loading
- if at any point a new
CSS resource (<style> tag) is encoutered, DOM building stops, a new CSSOM is built, existing CSSOM is replaced with the new one, everything already added to DOM is repainted and DOM building is resumed
- when
DOM building reaches the end </body> tag, document.ready is fired
- when all external resources have triggered
.load, window.load is fired
Given the above, you have three major cases:
- A. One or more
.css resources in <head> fail to resolve. They neither load nor return an error, they just stall (due to server or network problems). This behavior prevents any javascript from executing.
- B.
CSSOM is built but for various reasons DOM building is interrupted/stalled (usually by javascript errors or loops, serious HTML validation errors (such as multiple/nested <body> tags, etc) resulting in DOM not being finished. This might prevent document.ready from firing, but all javascript read up to the error is executed, so you could place a timer and reset it on document.ready which could initiate a window.location.replace() if not fired in a specified time window - the solution proposed by @nnnnnn, in his comment.
- C. All is well up to
document.ready, but some external resources do not load (media files/scripts). The best approach here would be to just re-initiate loading for the ones that haven't loaded, without losing the ones that already did. This is a possible solution - untested.
From your question, I believe you're falling into the A case. The B would likely drop some errors in your console and would be easy to spot/fix.
For A i'm thinking of a possible hack, but it's dirty, at least at first glance.
I'm thinking you should check which style-sheets usually stall loading and placing those at the beginning of <body> instead of inside <head>.
I know. This will automatically trigger a "No way!" reaction into any serious developers' mind, but let's see why it's not recommended. It's because you want to avoid FOUC at all costs.
And that's what normally happens when you place <style> tags in <body>. A new CSSOM is built, replacing the old one, existing content is repainted (causing FOUC) and DOM building is resumed. But if no content is placed before those <style> tags, nothing should be repainted and you benefit from javascript being executed before your problematic style-sheets are loaded.
How exactly you're going to load CSS resources into <body> should probably be subject of another question but here are a few possible methods:
<style>@import url();</style> - not sure if its valid and might not work cross-browser
- adding
<link> tags to <head> using javascript
- after a bit of research, I found
this article, documenting the following technique of making <link> tags in <head> no longer block rendering or javascript execution (yes, you no longer need to place them in <body> using this):
<link rel="stylesheet" href="css.css"
media="none" onload="if(media!='all')media='all'">
What technique you chose to make javascript start the timer before the CSS currently blocking your page finishes loading is not so important. The idea is to allow a script to assess what was loaded after a while and decide whether or not to reload the page or just re-initiate the loading process for unresolved resources.
You will still face FOUC and probably the best way around it would be to place opacity:0; on <body> until all CSS loaded and fade it in via javascript on window.load.
Regarding the reloading solution itself, you should probably use
location.replace(location.href);
...to avoid creating a new entry into your browser's history.
I hope you'll find some of the above helpful. Regards.