How do you read CSS rule values with JavaScript?

后端 未结 16 1168
天涯浪人
天涯浪人 2020-11-21 21:02

I would like to return a string with all of the contents of a CSS rule, like the format you\'d see in an inline style. I\'d like to be able to do this without knowing what i

相关标签:
16条回答
  • 2020-11-21 21:27

    Have adapted julmot's answer in order to get a more complete result. This method will also return styles where the class is part for the selector.

    //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;    
        }
    }
    

    In addition, I've made a function which collects the css style definitions to the sub-tree of a root node your provide (through a jquery selector).

    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;
    }
    

    Note that if a class is defined several times with the same selector, the above function will only pick up the first. Note that the example uses jQuery (but cab relatively easily be rewritten to not use it)

    0 讨论(0)
  • 2020-11-21 21:27

    //works in IE, not sure about other browsers...

    alert(classes[x].style.cssText);
    
    0 讨论(0)
  • 2020-11-21 21:30

    Since the accepted answer from "nsdel" is only avilable with one stylesheet in a document this is the adapted full working solution:

        /**
         * 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;
                    }
                }
            }
    
        }
    

    Notice: The selector must be the same as in the CSS.

    0 讨论(0)
  • 2020-11-21 21:33
    const getStyle = query => [...document.querySelector(query).computedStyleMap().entries()].map(e=>(e[1]+=[],e)).map(e=>e.join`:`+';').join`\n`
    

    In one line, prints out generated css for any query.

    0 讨论(0)
  • Here is code to iterate through all rules in a page:

    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' : '')+' }');
    });

    0 讨论(0)
  • 2020-11-21 21:39

    I made a similar helper function which shows the unneeded styles for this page. appends a <div> to the body listing all styles that where not used.

    (to be used with the firebug console)

    (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
    })()
    
    0 讨论(0)
提交回复
热议问题