How to dynamically create CSS class in JavaScript and apply?

后端 未结 15 1321
长情又很酷
长情又很酷 2020-11-22 02:57

I need to create a CSS stylesheet class dynamically in JavaScript and assign it to some HTML elements like - div, table, span, tr, etc and to some controls like asp:Textbox,

15条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-11-22 03:45

    I was looking through some of the answers here, and I couldn't find anything that automatically adds a new stylesheet if there are none, and if not simply modifies an existing one that already contains the style needed, so I made a new function (should work accross all browsers, though not tested, uses addRule and besides that only basic native JavaScript, let me know if it works):

    function myCSS(data) {
        var head = document.head || document.getElementsByTagName("head")[0];
        if(head) {
            if(data && data.constructor == Object) {
                for(var k in data) {
                    var selector = k;
                    var rules = data[k];
    
                    var allSheets = document.styleSheets;
                    var cur = null;
    
                    var indexOfPossibleRule = null,
                        indexOfSheet = null;
                    for(var i = 0; i < allSheets.length; i++) {
                        indexOfPossibleRule = findIndexOfObjPropInArray("selectorText",selector,allSheets[i].cssRules);
                        if(indexOfPossibleRule != null) {
                            indexOfSheet = i;
                            break;
                        }
                    }
    
                    var ruleToEdit = null;
                    if(indexOfSheet != null) {
    
                        ruleToEdit = allSheets[indexOfSheet].cssRules[indexOfPossibleRule];
    
                    } else {
                        cur = document.createElement("style");
                        cur.type =  "text/css";
                        head.appendChild(cur);
                        cur.sheet.addRule(selector,"");
                        ruleToEdit = cur.sheet.cssRules[0];
                        console.log("NOPE, but here's a new one:", cur);
                    }
                    applyCustomCSSruleListToExistingCSSruleList(rules, ruleToEdit, (err) => {
                        if(err) {
                            console.log(err);
                        } else {
                            console.log("successfully added ", rules, " to ", ruleToEdit);
                        }
                    });
                }
            } else {
                console.log("provide one paramter as an object containing the cssStyles, like: {\"#myID\":{position:\"absolute\"}, \".myClass\":{background:\"red\"}}, etc...");
            }
        } else {
            console.log("run this after the page loads");
        }
    
    };  
    

    then just add these 2 helper functions either inside the above function, or anywhere else:

    function applyCustomCSSruleListToExistingCSSruleList(customRuleList, existingRuleList, cb) {
        var err = null;
        console.log("trying to apply ", customRuleList, " to ", existingRuleList);
        if(customRuleList && customRuleList.constructor == Object && existingRuleList && existingRuleList.constructor == CSSStyleRule) {
            for(var k in customRuleList) {
                existingRuleList["style"][k] = customRuleList[k];
            }
    
        } else {
            err = ("provide first argument as an object containing the selectors for the keys, and the second argument is the CSSRuleList to modify");
        }
        if(cb) {
            cb(err);
        }
    }
    
    function findIndexOfObjPropInArray(objPropKey, objPropValue, arr) {
        var index = null;
        for(var i = 0; i < arr.length; i++) {
            if(arr[i][objPropKey] == objPropValue) {
                index = i;
                break;
            }
        }
        return index;
    }
    

    (notice that in both of them I use a for loop instead of .filter, since the CSS style / rule list classes only have a length property, and no .filter method.)

    Then to call it:

    myCSS({
        "#coby": {
            position:"absolute",
            color:"blue"
        },
        ".myError": {
            padding:"4px",
            background:"salmon"
        }
    })
    

    Let me know if it works for your browser or gives an error.

提交回复
热议问题