web-dev-qa-db-fra.com

Obtenir une valeur CSS à partir d'une feuille de style externe avec Javascript/jQuery

Est-il possible d'obtenir une valeur du CSS externe d'une page si l'élément auquel le style fait référence n'a pas encore été généré? (l'élément doit être généré dynamiquement).

La méthode jQuery que j'ai vue est $('element').css('property');, mais elle repose sur element étant sur la page. Existe-t-il un moyen de déterminer le type de propriété défini dans la CSS plutôt que le style calculé d'un élément?

Devrai-je faire quelque chose de moche comme ajouter une copie cachée de l'élément à ma page pour pouvoir accéder à ses attributs de style?

58
Acorn

Avec jQuery:

// Scoping function just to avoid creating a global
(function() {
    var $p = $("<p></p>").hide().appendTo("body");
    console.log($p.css("color"));
    $p.remove();
})();
p {color: blue}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Utiliser le DOM directement:

// Scoping function just to avoid creating a global
(function() {
    var p = document.createElement('p');
    document.body.appendChild(p);
    console.log(getComputedStyle(p).color);
    document.body.removeChild(p);
})();
p {color: blue}

Remarque: Dans les deux cas, si vous chargez des feuilles de style externes, vous devrez attendre leur chargement afin de voir leur effet sur l'élément. Ni la variable ready de jQuery ni l'événement DOMContentLoaded du DOM ne le permettent, vous devez le vérifier en surveillant qu'ils soient chargés .

57
karim79

Normalement, vous devriez laisser le navigateur appliquer toutes les règles, puis lui demander les résultats, mais dans les rares cas où vous avez vraiment besoin de tirer la valeur de la feuille de style, vous pouvez utiliser ceci: ( JSFiddle )

function getStyleSheetPropertyValue(selectorText, propertyName) {
    // search backwards because the last match is more likely the right one
    for (var s= document.styleSheets.length - 1; s >= 0; s--) {
        var cssRules = document.styleSheets[s].cssRules ||
                document.styleSheets[s].rules || []; // IE support
        for (var c=0; c < cssRules.length; c++) {
            if (cssRules[c].selectorText === selectorText) 
                return cssRules[c].style[propertyName];
        }
    }
    return null;
}

alert(getStyleSheetPropertyValue("p", "color"));

Notez que ceci est assez fragile, car vous devez fournir le texte de sélecteur complet qui correspond à la règle que vous recherchez (il n'est pas analysé) et qui ne gère pas les entrées en double ou les règles de priorité. Il est difficile pour moi de penser à un cas où l’utiliser serait une bonne idée, mais ici c’est juste un exemple.

16
Old Pro

En réponse à Karim79, je pensais juste que je jetterais ma version fonctionnelle de cette réponse. J'ai dû le faire plusieurs fois, alors voici ce que j'ai écrit:

function getClassStyles(parentElem, selector, style){
    elemstr = '<div '+ selector +'></div>';
    var $elem = $(elemstr).hide().appendTo(parentElem);
        val = $elem.css(style);
    $elem.remove();
    return val;
}
val = getClassStyles('.container:first', 'class="title"', 'margin-top');
console.warn(val);

Cet exemple suppose que vous avez et un élément avec class = "conteneur" et que vous recherchez le style de marge supérieure de la classe title dans cet élément. Bien sûr, changez pour répondre à vos besoins. 

Dans la feuille de style:

 .container .title{ margin-top:num; }

Dites-moi ce que vous pensez - Souhaitez-vous le modifier et si oui comment? Merci!

6
David Hobs

J'ai écrit une fonction d'assistance qui accepte un objet avec les attributs css à récupérer de la classe css donnée et complète les valeurs d'attribut css réelles .

function getStyleSheetValues(colScheme) {
    var tags='';
    var obj= colScheme;

    // enumerate css classes from object
    for (var prop in obj) { 
        if (obj.hasOwnProperty(prop) && typeof obj[prop]=="object") { 
            tags+= '<span class="'+prop+'"></span>';
        } 
    } 

    // generate an object that uses the given classes
    tags= $('<div>'+tags+'</div>').hide().appendTo("body");

    // read the class properties from the generated object
    var idx= 0;
    for (var prop in obj) { 
        if (obj.hasOwnProperty(prop) && typeof obj[prop]=="object") { 
            var nobj= obj[prop];
            for (var nprop in nobj) { 
                if (nobj.hasOwnProperty(nprop) && typeof(nobj[nprop])=="string") { 
                    nobj[nprop]= tags.find("span:eq("+idx+")").css(nobj[nprop]);
                }
            }
            idx++;
        } 
    } 
    tags.remove();
}

// build an object with css class names where each class name contains one 
// or more properties with an arbitrary name and the css attribute name as its value.
// This value will be replaced by the actual css value for the respective class.
var colorScheme= { chart_wall: {wallColor:'background-color',wallGrid:'color'}, chart_line1: { color:'color'} };

$(document).ready(function() {
    getStyleSheetValues(colorScheme);

    // debug: write the property values to the console;     
    if (window.console) {
        var obj= colorScheme;
        for (var prop in obj) { 
            if (obj.hasOwnProperty(prop) && typeof obj[prop]=="object") { 
                var nobj= obj[prop];
                for (var nprop in nobj) { 
                    if (nobj.hasOwnProperty(nprop)) { 
                        console.log(prop+'.'+nprop +':'+ nobj[nprop]);
                    }
                }
            } 
        } 
        // example of how to read an individual css attribute value
        console.log('css value for chart_wall.wallGrid: '+colorScheme.chart_wall.wallGrid);
    }
});
2
Marc Derksen

J'ai écrit cette fonction js, semble fonctionner aussi pour les classes imbriquées:

usage:

var style = get_css_property('.container-class .sub-container-class .child-class', 'margin');
console.log('style');


function get_css_property(class_name, property_name){
    class_names = class_name.split(/\s+/);
    var container = false;
    var child_element = false;

    for (var i = class_names.length - 1; i >= 0; i--) {
        if(class_names[i].startsWith('.'))
            class_names[i] = class_names[i].substring(1);
        var new_element = $.parseHTML('<div class="' + class_names[i] + '"></div>');
        if(!child_element)
            child_element = new_element;
        if(container)
            $(new_element).append(container);
        container = new_element;
    }
    $(container).hide().appendTo('body');
    var style = $(child_element).css(property_name);
    $(container).remove();
    return style;
}
0
fenadoruk