How to create a fallback in importing CSS files?

12

In How should I work with Bootstrap and JavaScript links? , how to serve the files media, either via CDN server or local server, it was answered that it is interesting to keep the two: initially loading the file from the CDN and, in case of failure, having a fallback on the local server, such as it is done with jQuery:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="/js/jquery-1.10.2.min.js"><\/script>')</script>

With JavaScript files, creating this fallback is trivial, as you just need to check the existence of the object, such as window.jQuery || ... , but with other files such as CSS and images, this is not so trivial.

So how can you define a fallback to import CSS files?

The idea would be to look something like this:

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script>bootstrapLoaded || document.write('<link rel="stylesheet" href="assets/css/bootstrap/3.3.7/css/bootstrap.min.css">')</script>

What is Fallback?

    
asked by anonymous 01.06.2018 / 22:19

2 answers

3

Test the number of rules of the chosen css, The following script will only test a css if it was loaded, it is at your discretion if you want to test more than one create an array of objects with the path of the external css you want to test and the related local css, and cycle with a for test one by one. Ex:

var cssTestar = [{externo: "caminhoexterno", local: "caminholocal"},{externo: "caminhoexterno", local: "caminholocal"}];

I recommend putting the following javascript block as the last head element;

<script type="text/javascript">
    for (var i = 0; i < document.styleSheets.length; i++) {
        var sheet = document.styleSheets[i];
        if (!sheet.href) {
            continue;
        }
        if(sheet.href=='https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrapnaoexiste.min.css') {
            var qtdRules = 0;
            try {
                var rules = sheet.hasOwnProperty("rules") && sheet.rules ? sheet.rules : (sheet.hasOwnProperty("cssRules") ? sheet.cssRules : []);
                qtdRules = rules.length;
            } finally {
                if (qtdRules == 0) {
                    var link = document.createElement('link');
                    link.id = 'id';
                    link.rel = 'stylesheet';
                    link.type = "text/css";
                    link.href = "caminholocal/seucsslocal.css";
                    document.head.appendChild(link);
                }
            }
        }
    }
</script>

Example in the snippet: Note: when executing does not present anything in the result table but if you inspect it you will see the link tag with the "csslocal" created in head

<!DOCTYPE html>
<html>
<head>
	<title>teste</title>
	<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrapnaoexiste.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">

<script type="text/javascript">
	for (var i = 0; i < document.styleSheets.length; i++) {
		var sheet = document.styleSheets[i];
	    if (!sheet.href) {
	        continue;
	    }
	  	if(sheet.href=='https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrapnaoexiste.min.css') {
		  	var qtdRules = 0;
		    try {
				var rules = sheet.hasOwnProperty("rules") && sheet.rules ? sheet.rules : (sheet.hasOwnProperty("cssRules") ? sheet.cssRules : []);
				qtdRules = rules.length;
			} finally {
				if (qtdRules == 0) {
					var link = document.createElement('link');
				    link.id = 'id';
				    link.rel = 'stylesheet';
				    link.type = "text/css";
				    link.href = "caminholocal/seucsslocal.css";
				    document.head.appendChild(link);
				}
			}
		}
	}
</script>
</head>
<body>
</body>
</html>
    
02.06.2018 / 00:58
3

According to MDN documentation you can use the onerror event in the link tag that loads the CSS. If the file fails to load, you can call a JavaScript function in the event:

                                                     evento     chama a função
                                                        ↓             ↓
<link rel="stylesheet" href="//...arquivoRemoto.css" onerror="cssNaoCarregado()" />

In the function, you insert in the head of the page the tag <link> with the local file:

<script>
function cssNaoCarregado(){
   var css = document.createElement("link");
   css.rel = "stylesheet";
   css.href = "arquivoLocal.css";
   document.querySelector("head").appendChild(css);
}
</script>
  

Note: does not work in Microsoft browsers. In these browsers, even if the file has not been loaded, it calls the event onload ( <link rel="stylesheet" onload="função()"...> ), as if it had been loaded.

    
10.06.2018 / 05:16