it-swarm.com.de

Wie liest man CSS-Regelwerte mit JavaScript?

Ich möchte einen String mit dem gesamten Inhalt einer CSS-Regel zurückgeben, wie das Format, das Sie in einem Inline-Stil sehen würden. Ich möchte in der Lage sein, dies zu tun, ohne zu wissen, was in einer bestimmten Regel enthalten ist, also kann ich sie nicht einfach nach Stilnamen herausziehen (wie .style.width etc.)

Das CSS:

.test {
    width:80px;
    height:50px;
    background-color:#808080;
}

Der Code bisher:

function getStyle(className) {
    var classes = document.styleSheets[0].rules || document.styleSheets[0].cssRules
    for(var x=0;x<classes.length;x++) {
        if(classes[x].selectorText==className) {
            //this is where I can collect the style information, but how?
        }
    }
}
getStyle('.test')

Adaptiert von hier , basierend auf der Antwort von scunliffe:

function getStyle(className) {
    var classes = document.styleSheets[0].rules || document.styleSheets[0].cssRules;
    for (var x = 0; x < classes.length; x++) {
        if (classes[x].selectorText == className) {
            (classes[x].cssText) ? alert(classes[x].cssText) : alert(classes[x].style.cssText);
        }
    }
}
getStyle('.test');
79
nsdel

Da die akzeptierte Antwort von "nsdel" nur mit einem Stylesheet in einem Dokument verfügbar ist, handelt es sich um die angepasste, voll funktionsfähige Lösung:

    /**
     * Gets styles by a classname
     * 
     * @notice The className must be 1:1 the same as in the CSS
     * @param string className_
     */
    function getStyle(className_) {

        var styleSheets = window.document.styleSheets;
        var styleSheetsLength = styleSheets.length;
        for(var i = 0; i < styleSheetsLength; i++){
            var classes = styleSheets[i].rules || styleSheets[i].cssRules;
            if (!classes)
                continue;
            var classesLength = classes.length;
            for (var x = 0; x < classesLength; x++) {
                if (classes[x].selectorText == className_) {
                    var ret;
                    if(classes[x].cssText){
                        ret = classes[x].cssText;
                    } else {
                        ret = classes[x].style.cssText;
                    }
                    if(ret.indexOf(classes[x].selectorText) == -1){
                        ret = classes[x].selectorText + "{" + ret + "}";
                    }
                    return ret;
                }
            }
        }

    }

Hinweis: Der Selektor muss derselbe sein wie im CSS.

21
dude

LÖSUNG 1 (CROSS-BROWSER)

function GetProperty(classOrId,property){ 
    var FirstChar = classOrId.charAt(0);  var Remaining= classOrId.substring(1);
    var elem = (FirstChar =='#') ?  document.getElementById(Remaining) : document.getElementsByClassName(Remaining)[0];
    return window.getComputedStyle(elem,null).getPropertyValue(property);
}

alert(  GetProperty(".my_site_title","position") ) ;

LÖSUNG 2 (CROSS-BROWSER)

function GetStyle(CLASSname) {
    var styleSheets = document.styleSheets;
    var styleSheetsLength = styleSheets.length;
    for(var i = 0; i < styleSheetsLength; i++){
        if (styleSheets[i].rules ) { var classes = styleSheets[i].rules; }
        else { 
            try {  if(!styleSheets[i].cssRules) {continue;} } 
            //Note that SecurityError exception is specific to Firefox.
            catch(e) { if(e.name == 'SecurityError') { console.log("SecurityError. Cant readd: "+ styleSheets[i].href);  continue; }}
            var classes = styleSheets[i].cssRules ;
        }
        for (var x = 0; x < classes.length; x++) {
            if (classes[x].selectorText == CLASSname) {
                var ret = (classes[x].cssText) ? classes[x].cssText : classes[x].style.cssText ;
                if(ret.indexOf(classes[x].selectorText) == -1){ret = classes[x].selectorText + "{" + ret + "}";}
                return ret;
            }
        }
    }
}

alert(GetStyle('.my_site_title'));
12
T.Todua

Einige Browser-Unterschiede, die Sie beachten sollten:

Angesichts des CSS:

div#a { ... }
div#b, div#c { ... }

in InsDels Beispiel haben Klassen 2 Klassen in FF und 3 Klassen in IE7.

Mein Beispiel zeigt dies:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <style>
    div#a { }
    div#b, div#c { }
    </style>
    <script>
    function PrintRules() {
    var rules = document.styleSheets[0].rules || document.styleSheets[0].cssRules
        for(var x=0;x<rules.length;x++) {
            document.getElementById("rules").innerHTML += rules[x].selectorText + "<br />";
        }
    }
    </script>
</head>
<body>
    <input onclick="PrintRules()" type="button" value="Print Rules" /><br />
    RULES:
    <div id="rules"></div>
</body>
</html>
6
Larsenal
function getStyle(className) {
    document.styleSheets.item("menu").cssRules.item(className).cssText;
}
getStyle('.test')

Hinweis: "menu" ist eine Element-ID, auf die Sie CSS angewendet haben. "className" Ein CSS-Klassenname, den wir benötigen, um seinen Text zu erhalten.

2
sivaprakasht

Hier ist Code zum Durchlaufen aller Regeln auf einer Seite:

function iterateCSS(f) {
  for (const styleSheet of window.document.styleSheets) {
    const classes = styleSheet.rules || styleSheet.cssRules;
    if (!classes) continue;

    for (const cssRule of classes) {
      if (cssRule.type !== 1 || !cssRule.style) continue;
      const selector = cssRule.selectorText, style=cssRule.style;
      if (!selector || !style.cssText) continue;
      for (let i=0; i<style.length; i++) {
        const propertyName=style.item(i);
        if (f(selector, propertyName, style.getPropertyValue(propertyName), style.getPropertyPriority(propertyName), cssRule)===false) return;
      }
    }
  }
}

iterateCSS( (selector, propertyName, propertyValue, propertyPriority, cssRule) => {
  console.log(selector+' { '+propertyName+': '+propertyValue+(propertyPriority==='important' ? ' !important' : '')+' }');
});
2
kofifus

Ich habe keinen der Vorschläge gefunden, um wirklich zu arbeiten. Hier ist eine robustere, die den Abstand beim Finden von Klassen normalisiert.

//Inside closure so that the inner functions don't need regeneration on every call.
const getCssClasses = (function () {
    function normalize(str) {
        if (!str)  return '';
        str = String(str).replace(/\s*([>~+])\s*/g, ' $1 ');  //Normalize symbol spacing.
        return str.replace(/(\s+)/g, ' ').trim();           //Normalize whitespace
    }
    function split(str, on) {               //Split, Trim, and remove empty elements
        return str.split(on).map(x => x.trim()).filter(x => x);
    }
    function containsAny(selText, ors) {
        return selText ? ors.some(x => selText.indexOf(x) >= 0) : false;
    }
    return function (selector) {
        const logicalORs = split(normalize(selector), ',');
        const sheets = Array.from(window.document.styleSheets);
        const ruleArrays = sheets.map((x) => Array.from(x.rules || x.cssRules || []));
        const allRules = ruleArrays.reduce((all, x) => all.concat(x), []);
        return allRules.filter((x) => containsAny(normalize(x.selectorText), logicalORs));
    };
})();

Hier ist es in Aktion von der Chrome Konsole.

enter image description here

2
Derek Ziemba

Haben Sie die Antwort von julmot angepasst, um ein vollständigeres Ergebnis zu erhalten. Diese Methode gibt auch Stile zurück, bei denen die Klasse Teil des Selektors ist.

//Get all styles where the provided class is involved
//Input parameters should be css selector such as .myClass or #m
//returned as an array of tuples {selectorText:"", styleDefinition:""}
function getStyleWithCSSSelector(cssSelector) {
    var styleSheets = window.document.styleSheets;
    var styleSheetsLength = styleSheets.length;
    var arStylesWithCSSSelector = [];

    //in order to not find class which has the current name as prefix
    var arValidCharsAfterCssSelector = [" ", ".", ",", "#",">","+",":","["];

    //loop through all the stylessheets in the bor
    for(var i = 0; i < styleSheetsLength; i++){
        var classes = styleSheets[i].rules || styleSheets[i].cssRules;
        var classesLength = classes.length;
        for (var x = 0; x < classesLength; x++) {
            //check for any reference to the class in the selector string
            if(typeof classes[x].selectorText != "undefined"){
                var matchClass = false;

                if(classes[x].selectorText === cssSelector){//exact match
                    matchClass=true;
                }else {//check for it as part of the selector string
                    //TODO: Optimize with regexp
                    for (var j=0;j<arValidCharsAfterCssSelector.length; j++){
                        var cssSelectorWithNextChar = cssSelector+ arValidCharsAfterCssSelector[j];

                        if(classes[x].selectorText.indexOf(cssSelectorWithNextChar)!=-1){
                            matchClass=true;
                            //break out of for-loop
                            break;
                        }
                    }
                }

                if(matchClass === true){
                    //console.log("Found "+ cssSelectorWithNextChar + " in css class definition " + classes[x].selectorText);
                    var styleDefinition;
                    if(classes[x].cssText){
                        styleDefinition = classes[x].cssText;
                    } else {
                        styleDefinition = classes[x].style.cssText;
                    }
                    if(styleDefinition.indexOf(classes[x].selectorText) == -1){
                        styleDefinition = classes[x].selectorText + "{" + styleDefinition + "}";
                    }
                    arStylesWithCSSSelector.Push({"selectorText":classes[x].selectorText, "styleDefinition":styleDefinition});
                }
            }
        }
    }
    if(arStylesWithCSSSelector.length==0) {
        return null;
    }else {
        return arStylesWithCSSSelector;    
    }
}

Außerdem habe ich eine Funktion erstellt, die die CSS-Stildefinitionen im Unterbaum eines Root-Knotens sammelt, den Sie bereitstellen (über einen JQuery-Selektor).

function getAllCSSClassDefinitionsForSubtree(selectorOfRootElement){
    //stack in which elements are pushed and poped from
    var arStackElements = [];
    //dictionary for checking already added css class definitions
    var existingClassDefinitions = {}

    //use jquery for selecting root element
    var rootElement = $(selectorOfRootElement)[0];
    //string with the complete CSS output
    var cssString = "";

    console.log("Fetching all classes used in sub tree of " +selectorOfRootElement);
    arStackElements.Push(rootElement);
    var currentElement;

    while(currentElement = arStackElements.pop()){
        currentElement = $(currentElement);
        console.log("Processing element " + currentElement.attr("id"));

        //Look at class attribute of element 
        var classesString = currentElement.attr("class");
        if(typeof classesString != 'undefined'){
            var arClasses = classesString.split(" ");

            //for each class in the current element
            for(var i=0; i< arClasses.length; i++){

                //fetch the CSS Styles for a single class. Need to append the . char to indicate its a class
                var arStylesWithCSSSelector = getStyleWithCSSSelector("."+arClasses[i]);
                console.log("Processing class "+ arClasses[i]);

                if(arStylesWithCSSSelector != null){
                    //console.log("Found "+ arStylesWithCSSSelector.length + " CSS style definitions for class " +arClasses[i]);
                    //append all found styles to the cssString
                    for(var j=0; j< arStylesWithCSSSelector.length; j++){
                        var tupleStyleWithCSSSelector = arStylesWithCSSSelector[j];

                        //check if it has already been added
                        if(typeof existingClassDefinitions[tupleStyleWithCSSSelector.selectorText] === "undefined"){
                            //console.log("Adding " + tupleStyleWithCSSSelector.styleDefinition);
                            cssString+= tupleStyleWithCSSSelector.styleDefinition;
                            existingClassDefinitions[tupleStyleWithCSSSelector.selectorText] = true;
                        }else {
                            //console.log("Already added " + tupleStyleWithCSSSelector.styleDefinition);
                        }
                    }
                }
            }
        }
        //Push all child elments to stack
        if(currentElement.children().length>0){
            arStackElements= arStackElements.concat(currentElement.children().toArray());
        }
    }

    console.log("Found " + Object.keys(existingClassDefinitions).length + " CSS class definitions");
    return cssString;
}

Beachten Sie, dass die obige Funktion nur die erste aufnimmt, wenn eine Klasse mehrmals mit demselben Selektor definiert wird. Beachten Sie, dass das Beispiel jQuery verwendet (aber cab kann relativ einfach umgeschrieben werden, um es nicht zu verwenden).

1
dparnas

Ich habe eine ähnliche Hilfsfunktion erstellt, die die nicht benötigten Stile für diese Seite anzeigt. Fügt dem Body ein <div> hinzu, in dem alle Stile aufgelistet sind, die nicht verwendet wurden.

(zur Verwendung mit der Firebug-Konsole)

(function getStyles(){var CSSrules,allRules,CSSSheets, unNeeded, currentRule;
CSSSheets=document.styleSheets;

for(j=0;j<CSSSheets.length;j++){
for(i=0;i<CSSSheets[j].cssRules.length;i++){
    currentRule = CSSSheets[j].cssRules[i].selectorText;

    if(!document.querySelectorAll(currentRule).length){ 
       unNeeded+=CSSSheets[j].cssRules[i].cssText+"<br>"; 
  }       
 }
}

docBody=document.getElementsByTagName("body")[0];
allRulesContainer=document.createElement("div");
docBody.appendChild(allRulesContainer);
allRulesContainer.innerHTML=unNeeded+isHover;
return false
})()
1
adardesign

Ich habe die Rückgabe eines Objekts hinzugefügt, bei dem Attribute nach Stil/Werten analysiert werden:

var getClassStyle = function(className){
    var x, sheets,classes;
    for( sheets=document.styleSheets.length-1; sheets>=0; sheets-- ){
        classes = document.styleSheets[sheets].rules || document.styleSheets[sheets].cssRules;
        for(x=0;x<classes.length;x++) {
            if(classes[x].selectorText===className){
                classStyleTxt = (classes[x].cssText ? classes[x].cssText : classes[x].style.cssText).match(/\{\s*([^{}]+)\s*\}/)[1];
                var classStyles = {};
                var styleSets = classStyleTxt.match(/([^;:]+:\s*[^;:]+\s*)/g);
                for(y=0;y<styleSets.length;y++){
                    var style = styleSets[y].match(/\s*([^:;]+):\s*([^;:]+)/);
                    if(style.length > 2)
                        classStyles[style[1]]=style[2];
                }
                return classStyles;
            }
        }
    }
    return false;
};
0
sledmouth

Diese Version durchsucht alle Stylesheets auf einer Seite. Für meine Bedürfnisse waren die Styles normalerweise im vorletzten der über 20 Stylesheets, also überprüfe ich sie rückwärts.

    var getStyle = function(className){
        var x, sheets,classes;
        for( sheets=document.styleSheets.length-1; sheets>=0; sheets-- ){
            classes = document.styleSheets[sheets].rules || document.styleSheets[sheets].cssRules;
            for(x=0;x<classes.length;x++) {
                if(classes[x].selectorText===className) {
                    return  (classes[x].cssText ? classes[x].cssText : classes[x].style.cssText);
                }
            }
        }
        return false;
    };
0
grigb

// Funktioniert im IE, nicht sicher über andere Browser ...

alert(classes[x].style.cssText);
0
scunliffe