web-dev-qa-db-fra.com

Comment utiliser Javascript pour vérifier et charger le CSS s'il n'est pas chargé?

Je dois vérifier (en Javascript) si un fichier CSS est chargé et sinon, le charger. jQuery va bien.

52
SaltLake

Il suffit de vérifier si un élément <link> existe avec l'attribut href défini sur l'URL de votre fichier CSS:

if (!$("link[href='/path/to.css']").length)
    $('<link href="/path/to.css" rel="stylesheet">').appendTo("head");

La méthode plain ol 'JS est aussi simple, elle utilise la collection document.styleSheets :

function loadCSSIfNotAlreadyLoadedForSomeReason () {
    var ss = document.styleSheets;
    for (var i = 0, max = ss.length; i < max; i++) {
        if (ss[i].href == "/path/to.css")
            return;
    }
    var link = document.createElement("link");
    link.rel = "stylesheet";
    link.href = "/path/to.css";

    document.getElementsByTagName("head")[0].appendChild(link);
}
loadCSSIfNotAlreadyLoadedForSomeReason();
83
Andy E

Je devais juste écrire quelque chose comme ça et je voulais le partager. Celui-ci est préparé pour plusieurs cas.

  • S'il n'y a pas de demande pour le fichier css (le fichier css n'est pas lié ...)
  • S'il y a une demande pour le fichier css, mais si cela a échoué (le fichier css n'est plus disponible ...)

var styles = document.styleSheets;
for (var i = 0; i < styles.length; i++) {
    // checking if there is a request for template.css
    if (styles[i].href.match("template")) {
        console.log("(Iteration: " + i + ") Request for template.css is found.");
        // checking if the request is not successful
        // when it is successful .cssRules property is set to null
        if (styles[i].cssRules != null && styles[i].cssRules.length == 0) {
            console.log("(Iteration: " + i + ") Request for template.css failed.");
            // fallback, make your modification
            // since the request failed, we don't need to iterate through other stylesheets
            break;
        } else {
            console.log("(Iteration: " + i + ") Request for template.css is successful.");
            // template.css is loaded successfully, we don't need to iterate through other stylesheets
            break;
        }
    }
    // if there isn't a request, we fallback
    // but we need to fallback when the iteration is done
    // because we don't want to apply the fallback each iteration
    // it's not like our css file is the first css to be loaded
    else if (i == styles.length-1) {
        console.log("(Iteration: " + i + ") There is no request for template.css.");
        // fallback, make your modification
    }
}

Version TL; DR

var styles = document.styleSheets;
for (var i = 0; i < styles.length; i++) {
    if (styles[i].href.match("css-file-name-here")) {
        if (styles[i].cssRules != null && styles[i].cssRules.length == 0) {
            // request for css file failed, make modification
            break;
        }
    } else if (i == styles.length-1) {
        // there is no request for the css file, make modification
    }
}

Mise à jour : Comme ma réponse a reçu quelques votes positifs et que cela m'a amené à réviser le code, j'ai décidé de le mettre à jour.

// document.styleSheets holds the style sheets from LINK and STYLE elements
for (var i = 0; i < document.styleSheets.length; i++) {

    // Checking if there is a request for the css file
    // We iterate the style sheets with href attribute that are created from LINK elements
    // STYLE elements don't have href attribute, so we ignore them
    // We also check if the href contains the css file name
    if (document.styleSheets[i].href && document.styleSheets[i].href.match("/template.css")) {

        console.log("There is a request for the css file.");

        // Checking if the request is unsuccessful
        // There is a request for the css file, but is it loaded?
        // If it is, the length of styleSheets.cssRules should be greater than 0
        // styleSheets.cssRules contains all of the rules in the css file
        // E.g. b { color: red; } that's a rule
        if (document.styleSheets[i].cssRules.length == 0) {

            // There is no rule in styleSheets.cssRules, this suggests two things
            // Either the browser couldn't load the css file, that the request failed
            // or the css file is empty. Browser might have loaded the css file,
            // but if it's empty, .cssRules will be empty. I couldn't find a way to
            // detect if the request for the css file failed or if the css file is empty

            console.log("Request for the css file failed.");

            // There is a request for the css file, but it failed. Fallback
            // We don't need to check other sheets, so we break;
            break;
        } else {
            // If styleSheets.cssRules.length is not 0 (>0), this means 
            // rules from css file is loaded and the request is successful
            console.log("Request for the css file is successful.");
            break;
        }
    }
    // If there isn't a request for the css file, we fallback
    // But only when the iteration is done
    // Because we don't want to apply the fallback at each iteration
    else if (i == document.styleSheets.length - 1) {
        // Fallback
        console.log("There is no request for the css file.");
    }
}

TL; DR

for (var i = 0; i < document.styleSheets.length; i++) {
    if (document.styleSheets[i].href && document.styleSheets[i].href.match("/template.css")) {
        if (document.styleSheets[i].cssRules.length == 0) {
            // Fallback. There is a request for the css file, but it failed.
            break;
        }
    } else if (i == document.styleSheets.length - 1) {
        // Fallback. There is no request for the css file.
    }
}
14
akinuri

Lisez le commentaire de JFK sur la réponse acceptée:

J'ai compris la question comme suit: "comment vérifier si un fichier css est chargé ou non." Plutôt que "comment vérifier si l'élément Existe".

L'élément peut exister (et le chemin peut aussi être correct) mais il ne signifie pas que le fichier css a été chargé avec succès.

Si vous accédez à un élément de lien via getElementById, vous ne pourrez pas vérifier/lire le style défini dans le fichier CSS. 

Afin de vérifier si un style a été chargé avec succès, nous devons utiliser getComputedStyle (ou currentStyle pour IE).

HTML

//somewhere in your html document

<div id="css_anchor"></div>

CSS

//somewhere in your main stylesheet

#css_anchor{display:none;}

JAVASCRIPT

//js function to check the computed value of a style element

function get_computed_style(id, name){

        var element = document.getElementById(id);

        return element.currentStyle ? element.currentStyle[name] : window.getComputedStyle ? window.getComputedStyle(element, null).getPropertyValue(name) : null;

}

 //on document ready check if #css_anchor has been loaded

    $(document).ready( function() {

            if(get_computed_style('css_anchor', 'display')!='none'){

            //if #css_anchor style doesn't exist append an alternate stylesheet

                var alternateCssUrl = 'http://example.com/my_alternate_stylesheet.css';

                var stylesheet = document.createElement('link');

                stylesheet.href = alternateCssUrl;
                stylesheet.rel = 'stylesheet';
                stylesheet.type = 'text/css';
                document.getElementsByTagName('head')[0].appendChild(stylesheet);

            }
    });

Une partie de la réponse provient de: myDiv.style.display est vide lorsque défini dans la feuille de style principale

Démo ici: http://jsfiddle.net/R9F7R/

6
RafaSashi

Quelque chose comme ça fera (en utilisant jQuery):

function checkStyleSheet(url){
   var found = false;
   for(var i = 0; i < document.styleSheets.length; i++){
      if(document.styleSheets[i].href==url){
          found=true;
          break;
      }
   }
   if(!found){
       $('head').append(
           $('<link rel="stylesheet" type="text/css" href="' + url + '" />')
       );
   }
}
5
Sean Patrick Floyd

Mes 2 centimes Ceci vérifie si des règles sont définies sur le fichier css ou non, ce qui signifie qu’elles ont été chargées ou non.

if(jQuery("link[href='/style.css']").prop('sheet').cssRules.length == 0){
    //Load the css you want
}
3
jpbourbon

En dehors de toutes les bonnes réponses ci-dessus, vous pouvez simplement insérer un élément factice dans votre balisage et dans votre fichier CSS, lui attribuer un style autre que celui par défaut. Puis, dans le code, vérifiez si l'attribut est appliqué à l'élément factice et, dans le cas contraire, chargez le fichier css. Juste une pensée cependant, pas une manière élégante de faire la chose que vous voulez faire.

2
Samnan

L'objet document contient une collection de feuilles de style avec toutes les feuilles de style chargées.

Pour une référence, voir http://www.javascriptkit.com/domref/stylesheet.shtml

Vous pouvez boucler cette collection pour vérifier que la feuille de style que vous voulez vérifier y est et est donc chargée par le navigateur.

document.styleSheets[0] //access the first external style sheet on the page

Il existe toutefois des incompatibilités de navigateur que vous devriez rechercher.

1
Peter

Pour une expérience cohérente et répétable de Nice, j'ai écrit ces deux plugins jQuery qui imitent la méthode $.getScript(url, callback) jQuery (cependant, ils ne forceront PAS le rechargement du serveur comme $.getScript(). Il existe deux méthodes: l'une qui charge un fichier CSS à tout moment , et un qui ne le chargera qu’une fois. Je trouve le premier pratique lors du développement lorsque je fais des changements, et le second est idéal pour un déploiement rapide.

/**
 * An AJAX method to asynchronously load a CACHED CSS resource
 * Note: This removes the jQuery default behaviour of forcing a refresh by means
 * of appending a datestamp to the request URL. Actual caching WILL be subject to
 * server/browser policies
 */
$.getCachedCss = function getCachedCss(url, callback)
{
    $('<link>',{rel:'stylesheet', type:'text/css', 'href':url, media:'screen'}).appendTo('head');

    if (typeof callback == 'function')
        callback();
}

/**
 * An AJAX method to asynchronously load a CACHED CSS resource Only ONCE.
 * Note: This removes the jQuery default behaviour of forcing a refresh by means
 * of appending a datestamp to the request URL. Actual caching WILL be subject to
 * server/browser policies
 */
$.getCachedCssOnce = function getCachedCssOnce(url, callback)
{
    if (!$("link[href='" + url + "']").length) {
        $.getCachedCss(url, callback);

        if (typeof callback == 'function')
            callback();
    }
}

Exemple d'utilisation:

$(function() {
    $.getCachedCssOnce("pathToMyCss/main.css");
)}

Exemple d'utilisation avec rappel:

$(function() {
    $.getCachedCssOnce("pathToMyCss/main.css", function() {
        // Do something once the CSS is loaded
});
1
sean.boyer

Une façon: utilisez document.getElementsByTagName("link") parcourir sur chacun et vérifiez si href est égal au fichier CSS que vous vérifiez.

Autre moyen: si vous savez qu'une règle CSS est définie uniquement dans ce fichier, vérifiez si cette règle s'applique réellement, par exemple. vérifiez si le fond de quelque chose est vraiment rouge.

1
Shadow Wizard
var links = document.getElementsByTagName('link');
var file  = 'my/file.css';
var found = false;

for ( var i in links )
{
    if ( links[i].type == 'text/css' && file == links[i].href ) {
        found = true; break;
    }
}

if ( !( found ) ) {
    var styles = document.getElementsByTagName('style');
    var regexp = new RegExp('/\@import url\("?' + file + '"?\);/');

    for ( var i in styles )
    {
        if ( styles[i].src == file ) {
            found = true; break;
        } else if ( styles[i].innerHTML.match(regexp) ) {
            found = true; break;
        }
    }
}

if ( !( found ) ) {
    var Elm = document.createElement('link');
        Elm.href = file;
    document.documentElement.appendChild(Elm);
}
1
joksnet

Vous pouvez soit vérifier si le nom du fichier se trouve dans votre balisage, par exemple:

var lnks    = document.getElementsByTagName('link'),
    loadcss = true;

for(var link in lnks) {
    href = link.getAttribute('href');

    if( href.indexOf('foooobar.css') > -1) ){
            loadcss = false;
            return false;
    }
});

if( loadcss ) {
        var lnk     = document.createElement('link'),
            head    = document.getElementsByTagName('head')[0] || document.documentElement;        

        lnk.rel     = 'stylesheet';
        lnk.type    = 'text/css';
        lnk.href    = '//' + location.Host + 'foooobar.css';            

        head.insertBefore(lnk, head.firstChild);
}

ou vous pouvez rechercher une className spécifique qui devrait être disponible si la feuille de style a été chargée. Cela vient probablement un peu plus près d'une détection de fonctionnalité.

1
jAndy

moyen simple en utilisant javascript ..,

loadCssIfNotLoaded('https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css');
loadCssIfNotLoaded('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');

function loadCssIfNotLoaded(url) {
    var element=document.querySelectorAll('link[href="' + url + '"]');
    if (element.length == 0)
    {
        var link = document.createElement('link');
        link.rel = 'stylesheet';
        link.href = url;
        document.getElementsByTagName("head")[0].appendChild(link);
    }
}
0
Adith Suresh

Dans une ligne, avec jQuery. Si le #witness div est visible, nous devons charger le fichier css.

Dans le HTML, nous avons un:

<div id="witness"></div>

Dans le fichier CSS à charger, nous avons:

  #witness{display:none;}

Donc, si le fichier css est chargé, la div #witness n'est pas visible. Nous pouvons vérifier avec jQuery et prendre une décision.

!$('#witness').is(':visible') || loadCss() ;

En tant qu'extrait:

function loadCss(){
  //...
  console.log('Css file required');
};


!$('#witness').is(':visible') || loadCss();
#witness{display:none;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

<div id="witness"></div>

0
Philippe Perret

utilisez .sheet dans jQuery:

HTML:

<link rel="stylesheet" href="custom.css">

jQuery:

if($("link[href='custom.css']")[0].sheet.cssRules.length==0){
//custom.css was not loaded, do your backup loading here
}
0
xam