How to fallback to local stylesheet (not script) if CDN fails
Not cross-browser tested but I think this will work. Will have to be after you load jquery though, or you'll have to rewrite it in plain Javascript.
<script type="text/javascript">
$.each(document.styleSheets, function(i,sheet){
if(sheet.href=='http://code.jquery.com/mobile/1.0b3/jquery.mobile-1.0b3.min.css') {
var rules = sheet.rules ? sheet.rules : sheet.cssRules;
if (rules.length == 0) {
$('<link rel="stylesheet" type="text/css" href="path/to/local/jquery.mobile-1.0b3.min.css" />').appendTo('head');
}
}
})
</script>
Provide local fallback for CSS from CDN
This is what I have created for our needs. If this meets your needs, simply call the function ensureCssFileInclusion(file to check, boolean value). You will have to adjust it for your needs to make sure that you provide the cssFileToCheck, fallbackCssFile in this function.
/**
* Checks the page for given CSS file name to see if it was already included within page stylesheets.
* If it was, then this function does nothing else. If CSS file was not found among page stylesheets,
* then this function will attempt to load the stylesheet by adding an HTML link tag to the document
* HEAD section. You must also specify whether given cssFileToInclude is a relative path or an absolute path.
*/
ensureCssFileInclusion = function(cssFileToInclude, isRelativePath) {
if (isRelativePath) {
if (!window.location.origin) {
cssFileToInclude = window.location.protocol+"//"+window.location.host + cssFileToInclude;
}
}
var styleSheets = document.styleSheets;
for (var i = 0, max = styleSheets.length; i < max; i++) {
if (styleSheets[i].href == cssFileToInclude) {
return;
}
}
// because no matching stylesheets were found, we will add a new HTML link element to the HEAD section of the page.
var link = document.createElement("link");
link.rel = "stylesheet";
link.href = cssFileToInclude;
document.getElementsByTagName("head")[0].appendChild(link);
};
How to create fallback for CDN libraries without using document.write()
I recommend using 3p packages like fallback.js or require.js given they are more scalable in case you have multiple fallbacks and they give you faster loading performance.
Example of fallback.js
HTML CODE
<html>
<head>
<!-- **The `data-main` attribute tells the library to load `main.js`** -->
<script async data-main="main" src="fallback.min.js" type="text/javascript"></script>
</head>
<body>
</body>
</html>
MAIN JS FILE
cfg({
"libs": {
"jQuery": {
"urls": [
"//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min",
"//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min"
]
},
}
});
req(function(jQuery) {
jQuery("body");
});
Example of require.js
requirejs.config({
enforceDefine: true,
paths: {
jquery: [
'https://code.jquery.com/jquery-3.4.1.min.js',
//If the CDN location fails, load from this location
'js/jquery-3.4.1.min.js'
]
}
});
require(['jquery'], function ($) {});
How to load local script files as fallback in cases where CDN are blocked/unavailable?
To confirm that cdn script loaded you can check for existence any variable/function this script defines, if it is undefined - then cdn failed and you need to load local script copy.
On this principle are based solutions like that:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.5.1.min.js">\x3C/script>')</script>
(if there is no window.jQuery property defined cdn script didn't loaded).
You may build your own solutions using this method. For instance, jquery tooltip plugin creates $.tooltip()
function so we can check it with code like this:
<script>
if (typeof $.tooltip === 'undefined') {
document.write('<script src="js/libs/jquery.tooltip.min.js">\x3C/script>');
}
</script>
fallback to local bootstrap 4 css file
After experimenting further, I figured out that all I needed to do was to replace class="hidden"
with class="collapse"
.
Here the corrected code, in case someone wants to see/use it:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Bootstrap 4.1.1 CSS CDN -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css">
<title>Home | phpMIDAS viewer</title>
</head>
<body>
<!-- jQuery 3.3.1 CDN -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<!-- Bootstrap 4.1.1 JS CDN -->
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js" ></script>
<!-- Bootstrap 4.1.1 JS local fallback -->
<script>if(typeof($.fn.modal) === 'undefined') {document.write('<script src="bootstrap/js/bootstrap.min.js"><\/script>')}</script>
<!-- Bootstrap 4.1.1 CSS local fallback -->
<div id="bootstrapCssTest" class="collapse"></div>
<script>
$(function() {
if ($('#bootstrapCssTest').is(":visible")) {
$("head").prepend('<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">');
}
});
</script>
</body>
</html>
How to write a fallback for css files not loaded, loading too long and blocked?
Disclaimer
Seems like all of these very kind people have marked your question as a duplicate, however they didn't notice that the answer provided to that question does not work (the answer is from 2011 for god's sake, see why it doesn't work in the notes). I've already flagged it to moderators to see if they can unmark that.
Anyways, I've created a new demo for my updated answer taking into consideration your need to check for multiple cdn css files and how that may affect your websites performance. (I've used the head
method in the XMLHttpRequest()
which is faster according to this cool guy since it doesn't retrieve the pages body.
Also I've provided a format to easily replace failed external <link>
tags which their local counterpart.
JavaScript
CSSback = {
local: "cssfallback/",
fallbacks: {
"animate.min.css": "localanimate.css",
"nonexistent.min.css": "localnonexistent.css"
}
}
CSSback.init = function () {
var links = document.head.querySelectorAll("link");
for (var i = 0, l = links.length; i < l; i++) {
var link = links[i];
this.ping(link);
}
}.bind(CSSback);
CSSback.ping = function (link) {
var url = link.href;
var http = new XMLHttpRequest();
http.onreadystatechange = function () {
if (http.readyState == 4 && http.status != 200) this.fallback(link);
}.bind(this);
http.open("head", url, true);
http.send();
}.bind(CSSback);
CSSback.fallback = function (link) {
var url = link.href.split("/");
var name = url[url.length - 1];
var fallback = this.fallbacks[name];
if (fallback) {
link.parentNode.removeChild(link);
var link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = this.local + fallback;
document.head.appendChild(link);
}
}.bind(CSSback);
window.addEventListener("load", CSSback.init);
Usage
You should modify the CSSBack{}
's local
(for the path to the local stylesheets) and fallbacks
(for a key-value relationship between the name of the external stylesheet, and the name of the local stylesheet).
HTML
<link href="http://cdn.jsdelivr.net/animatecss/3.2.0/animate.min.css" (..) >
<link href="http://cdn.jsdelivr.net/animatecss/3.2.0/nonexistent.min.css" (..) >
Modified JavaScript
CSSback = {
local: "cssfallback/",
fallbacks: {
"animate.min.css": "localanimate.css",
"nonexistent.min.css": "localnonexistent.css"
}
}
If any <link>
fails, it will remove it and replace it with it's local counterpart, in this case nonexistent.min.css
will fail and it will be replaced leaving the final <link>
tags being:
<link href="http://cdn.jsdelivr.net/animatecss/3.2.0/animate.min.css" (..) >
<link href="cssfallback/nonexistent.css" (..) >
Notes
- A
<link>
will fail if it's response status is 0 (non-allowed) or 404 (not-found), that means if the stylesheet is online but it's server doesn't have aAccess-Control-Allow-Origin="*"
policy it will think it failed too. (Fortunately most cdn's have it, including yours). - The selected answer in the other question does not work because
document.styleSheets.cssRules
in external stylesheets returnsnull
in Chrome and Firefox just bluntly throws you a Security Error.
Hope it helps! :)
WordPress fallback for Bootstrap's CDN without relying on JavaScript?
After the first time the php script tries accessing the CSS file, the server returns a status code 304. The easiest implementation to check for this would be the following:
function bootstrap_css() {
$bootstrap_cdn = 'https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css';
$cdn_check = @get_headers($bootstrap_cdn);
if (strpos($cdn_check[0], "200") !== false || strpos($cdn_check[0], "304") !== false) :
wp_enqueue_style('bootstrap',$bootstrap_cdn,array(),'4.2.1');
function add_cross_origin($html,$handle) {
if ('bootstrap' === $handle) {
return str_replace("media='all'","media='all' integrity='sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS' crossorigin='anonymous'",$html);
}
return $html;
}
add_filter('style_loader_tag','add_cross_origin',10,2);
else :
wp_enqueue_style('bootstrap',get_site_url() . '/css/bootstrap.min.css',false,'4.2.1');
endif;
}
add_action('wp_enqueue_scripts','bootstrap_css');
Local fallback for jquery.js, bootstrap.css and bootstrap.js incase CDNs are down or locall internet is not working
It seems you already have the answer for this but encase it helps:
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/js/bootstrap.bundle.min.js"></script>
<script>
if (!window.bootstrap) {
// if the bootstrap object is not present
let bootstrapScript = document.createElement("script");
bootstrapScript.setAttribute("src", "frameworks/bootstrap.bundle.min.js");
document.getElementsByTagName("head")[0].appendChild(bootstrapScript);
}
</script>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/css/bootstrap.min.css"
onerror="this.onerror=null;this.href='frameworks/bootstrap.min.css';this.removeAttribute('integrity');this.removeAttribute('crossorigin');"
integrity=""
crossorigin="" />
I hope this is useful still
Related Topics
Custom CSS Properties, Why Not
Ios: Disable Bounce Scroll But Allow Normal Scrolling
Any Way to Hide CSS and JavaScript File from the Client-Side User
Need to Load Image as Modal on Click in Bootstrap CSS
Onclick Show Div, But Hide When Other One Is Clicked
Where in the HTML File Should Jquery and Bootstrap Be Placed
How to Have a Non-Rectangular Div
Making Links Active in JavaScript
Detect If Page Is Loaded Inside Wkwebview in JavaScript
Youtube API Not Working with iPad/Iphone/Non-Flash Device
Jquery Select a Div with a Certain Class, That Doesn't Have Another Class
Isotope Jquery Plugin Doesn't Show Properly on Chrome
Vertical-Align Text Within a Textarea
How to Get New Image Size Dimension After Giving Object-Fit:Contain Property to the Image Tag
Performance Difference Between JavaScript Created Inline Styles and JavaScript Created Stylesheets