我需要在JavaScript中动态创建CSS样式表类,并将其分配给一些HTML元素(例如div,表,span,tr等)以及一些控件(例如asp:Textbox,Dropdownlist和datalist)。

有可能吗?

配一个样本就好了。

评论

看看github.com/Box9/jss

另请参见stackoverflow.com/questions/1212500/…

#1 楼

尽管我不确定为什么要使用JavaScript创建CSS类,但这是一个选择:

var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = '.cssClass { color: #F00; }';
document.getElementsByTagName('head')[0].appendChild(style);

document.getElementById('someElementId').className = 'cssClass';


评论


我的用例是一个书签,它突出显示了某些元素以进行质量检查。

– TomG
2011年4月29日在19:14

可以肯定的是,这会导致IE 8及更低版本中出现未知的运行时错误。

–安迪·休姆(Andy Hume)
2011年10月31日上午10:52

我的用例是加载随机的Google网络字体,然后为randomFont类提供font-family :-)

– w00t
2012年2月15日在12:11

另一个用例是您想要一个不依赖CSS文件的JS库。就我而言,我想开箱即用的轻量级咆哮风格警报弹出窗口。

– xeolabs
13年8月12日在7:24

我正在做类似w00t的事情。我正在开发一个交互式html5应用程序,该应用程序将在画布上书写文字,我想让我的用户从多种字体中进行选择。我打算创建一个后端,而不是使用所有字体的通用CSS,而只在该后端上载字体数据,并且每当加载程序时,对Web服务的一个小小的调用都会带来字体并添加它们

– CJLopez
15年3月16日在20:02



#2 楼

找到了一个更好的解决方案,该解决方案可在所有浏览器上使用。
使用document.styleSheet添加或替换规则。可接受的答案简短易用,但这在IE8上也适用,而且也较少。

function createCSSSelector (selector, style) {
  if (!document.styleSheets) return;
  if (document.getElementsByTagName('head').length == 0) return;

  var styleSheet,mediaType;

  if (document.styleSheets.length > 0) {
    for (var i = 0, l = document.styleSheets.length; i < l; i++) {
      if (document.styleSheets[i].disabled) 
        continue;
      var media = document.styleSheets[i].media;
      mediaType = typeof media;

      if (mediaType === 'string') {
        if (media === '' || (media.indexOf('screen') !== -1)) {
          styleSheet = document.styleSheets[i];
        }
      }
      else if (mediaType=='object') {
        if (media.mediaText === '' || (media.mediaText.indexOf('screen') !== -1)) {
          styleSheet = document.styleSheets[i];
        }
      }

      if (typeof styleSheet !== 'undefined') 
        break;
    }
  }

  if (typeof styleSheet === 'undefined') {
    var styleSheetElement = document.createElement('style');
    styleSheetElement.type = 'text/css';
    document.getElementsByTagName('head')[0].appendChild(styleSheetElement);

    for (i = 0; i < document.styleSheets.length; i++) {
      if (document.styleSheets[i].disabled) {
        continue;
      }
      styleSheet = document.styleSheets[i];
    }

    mediaType = typeof styleSheet.media;
  }

  if (mediaType === 'string') {
    for (var i = 0, l = styleSheet.rules.length; i < l; i++) {
      if(styleSheet.rules[i].selectorText && styleSheet.rules[i].selectorText.toLowerCase()==selector.toLowerCase()) {
        styleSheet.rules[i].style.cssText = style;
        return;
      }
    }
    styleSheet.addRule(selector,style);
  }
  else if (mediaType === 'object') {
    var styleSheetLength = (styleSheet.cssRules) ? styleSheet.cssRules.length : 0;
    for (var i = 0; i < styleSheetLength; i++) {
      if (styleSheet.cssRules[i].selectorText && styleSheet.cssRules[i].selectorText.toLowerCase() == selector.toLowerCase()) {
        styleSheet.cssRules[i].style.cssText = style;
        return;
      }
    }
    styleSheet.insertRule(selector + '{' + style + '}', styleSheetLength);
  }
}


功能使用如下。

createCSSSelector('.mycssclass', 'display:none');


评论


确认使用IE8。我确实必须在mediaType for循环ifs中添加“ styleSheet.cssRules [i] .selectorText &&”和“ styleSheet.rules [i] .selectorText &&”,因为它在Chrome浏览器中无法正常工作,有时有时候selectorText不是没有定义。

– w00t
2012年2月15日在12:26

@ w00t您能否粘贴或编辑代码以使其正常工作?

–恒杰
13年5月17日在16:01

我刚刚打开Chrome浏览器(版本34.0.1847.132)并粘贴了函数并执行了它,但是它不起作用:“ TypeError:无法读取null的'length'属性”。从开发者控制台创建它可能不起作用吗?

– dnuske
14年5月4日,2:09



事实证明,某些版本的chrome(或chrome)不允许在索引0上插入insertRule。这是解决方法:styleSheet.insertRule(selector“”“

– dnuske
2014年5月5日19:17

@dnuske我遇到了同样的问题。事实证明styleSheet.cssRules的计算结果为null。我使用的解决方法是创建一个新变量var styleSheetLength = styleSheet.cssRules? styleSheet.cssRules.length:0并将其用法替换为函数的实现。

–拉杰·纳塔尼(Raj Nathani)
2014年7月5日,下午3:41

#3 楼

简短的答案,这是“在所有浏览器上”兼容的(特别是IE8 / 7): >
function createClass(name,rules){
    var style = document.createElement('style');
    style.type = 'text/css';
    document.getElementsByTagName('head')[0].appendChild(style);
    if(!(style.sheet||{}).insertRule) 
        (style.styleSheet || style.sheet).addRule(name, rules);
    else
        style.sheet.insertRule(name+"{"+rules+"}",0);
}
createClass('.whatever',"background-color: green;");


这里还有一些测试页:https://gist.github.com/shadybones/9816763

关键一点是事实该样式元素具有“ styleSheet” /“ sheet”属性,可用于在其中添加/删除规则。

评论


所以这会在每次创建类时创建一个新的“样式”元素?因此,如果我要基于数据在for循环中创建1000多个类,则需要将document.head.appendChild应用1000次?

– bluejayke
19年2月11日,1:17

对于我在chrome style.sheet和style.styleSheet中不存在

– bluejayke
19年2月11日,下午1:56

#4 楼

有一个简单的jQuery插件可以生成CSS声明:jQuery-injectCSS

事实上,它使用JSS(JSON描述的CSS),但是要生成动态CSS样式表,它很容易处理。 。

$.injectCSS({
    "#test": {
        height: 123
    }
});


评论


类似于stackoverflow.com/questions/1212500/…。

–user1742529
19-09-16在8:06

#5 楼

YUI到目前为止是我见过的最好的样式表实用程序。我鼓励您检查一下,但是这里有个味道:

// style element or locally sourced link element
var sheet = YAHOO.util.StyleSheet(YAHOO.util.Selector.query('style',null,true));

sheet = YAHOO.util.StyleSheet(YAHOO.util.Dom.get('local'));


// OR the id of a style element or locally sourced link element
sheet = YAHOO.util.StyleSheet('local');


// OR string of css text
var css = ".moduleX .alert { background: #fcc; font-weight: bold; } " +
          ".moduleX .warn  { background: #eec; } " +
          ".hide_messages .moduleX .alert, " +
          ".hide_messages .moduleX .warn { display: none; }";

sheet = new YAHOO.util.StyleSheet(css);


显然还有其他更简单的即时更改样式的方法,例如这里建议的方法。如果它们对您的问题有意义,那么可能是最好的选择,但是绝对有理由为什么修改css是更好的解决方案。最明显的情况是需要修改大量元素时。另一个主要情况是,如果需要样式更改以涉及级联。使用dom修改元素将始终具有更高的优先级。它是大锤方法,等效于直接在html元素上使用style属性。这并不总是想要的效果。

#6 楼

从IE 9开始,您现在可以加载文本文件并设置style.innerHTML属性。因此,基本上,您现在可以通过ajax加载一个css文件(并获取回调),然后将文本设置在这样的样式标签中。 。但是,只要您不需要支持IE8,它就可以工作。 br />
// RESULT: doesn't work in IE8 and below. Works in IE9 and other browsers.
$(document).ready(function() {
    // we want to load the css as a text file and append it with a style.
    $.ajax({
        url:'myCss.css',
        success: function(result) {
            var s = document.createElement('style');
            s.setAttribute('type', 'text/css');
            s.innerHTML = result;
            document.getElementsByTagName("head")[0].appendChild(s);
        },
        fail: function() {
            alert('fail');
        }
    })
});


#7 楼

这是Vishwanath的解决方案,略加注释:

function setStyle(cssRules, aSelector, aStyle){
    for(var i = 0; i < cssRules.length; i++) {
        if(cssRules[i].selectorText && cssRules[i].selectorText.toLowerCase() == aSelector.toLowerCase()) {
            cssRules[i].style.cssText = aStyle;
            return true;
        }
    }
    return false;
}

function createCSSSelector(selector, style) {
    var doc = document;
    var allSS = doc.styleSheets;
    if(!allSS) return;

    var headElts = doc.getElementsByTagName("head");
    if(!headElts.length) return;

    var styleSheet, media, iSS = allSS.length; // scope is global in a function
    /* 1. search for media == "screen" */
    while(iSS){ --iSS;
        if(allSS[iSS].disabled) continue; /* dont take into account the disabled stylesheets */
        media = allSS[iSS].media;
        if(typeof media == "object")
            media = media.mediaText;
        if(media == "" || media=='all' || media.indexOf("screen") != -1){
            styleSheet = allSS[iSS];
            iSS = -1;   // indication that media=="screen" was found (if not, then iSS==0)
            break;
        }
    }

    /* 2. if not found, create one */
    if(iSS != -1) {
        var styleSheetElement = doc.createElement("style");
        styleSheetElement.type = "text/css";
        headElts[0].appendChild(styleSheetElement);
        styleSheet = doc.styleSheets[allSS.length]; /* take the new stylesheet to add the selector and the style */
    }

    /* 3. add the selector and style */
    switch (typeof styleSheet.media) {
    case "string":
        if(!setStyle(styleSheet.rules, selector, style));
            styleSheet.addRule(selector, style);
        break;
    case "object":
        if(!setStyle(styleSheet.cssRules, selector, style));
            styleSheet.insertRule(selector + "{" + style + "}", styleSheet.cssRules.length);
        break;
    }


#8 楼

JSS是一个可以帮助您完成任务的有趣项目。


JSS是CSS的更好抽象。它使用JavaScript作为一种语言
,以声明性和可维护的方式描述样式。这是一个高性能的JS to CSS编译器,可在运行时在浏览器和服务器端运行。


JSS库允许您使用以下命令插入DOM / head部分.attach()函数。

请在线版本进行评估。

有关JSS的更多信息。

示例:

// Use plugins.
jss.use(camelCase())

// Create your style.
const style = {
  myButton: {
    color: 'green'
  }
}

// Compile styles, apply plugins.
const sheet = jss.createStyleSheet(style)

// If you want to render on the client, insert it into DOM.
sheet.attach()


#9 楼

使用Google闭包:

,您可以只使用ccsom模块:进入文档头。

#10 楼

https://jsfiddle.net/xk6Ut/256/

在JavaScript中动态创建和更新CSS类的一个选项:


使用样式元素创建一个CSS部分
为样式元素使用ID,以便我们可以更新CSS
class

.....

function writeStyles(styleName, cssText) {
    var styleElement = document.getElementById(styleName);
    if (styleElement) 
             document.getElementsByTagName('head')[0].removeChild(
        styleElement);
    styleElement = document.createElement('style');
    styleElement.type = 'text/css';
    styleElement.id = styleName;
    styleElement.innerHTML = cssText;
    document.getElementsByTagName('head')[0].appendChild(styleElement);
}


...

    var cssText = '.testDIV{ height:' + height + 'px !important; }';
    writeStyles('styles_js', cssText)


#11 楼

我在这里查看了一些答案,但找不到任何可以自动添加新样式表的东西,如果没有,那么就不能简单地修改已经包含所需样式的现有样式表,所以我做了一个新功能(应该在所有浏览器上都可以使用,尽管未经测试,但使用addRule,并且除了仅基本的本机JavaScript之外,请让我知道是否可以使用): helper函数可以在上述函数内部,也可以在其他任何地方:

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

};  


(请注意,由于CSS样式,在这两种方法中我都使用for循环而不是.filter /规则列表类仅具有length属性,而没有.filter方法。)然后调用它:

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


让我知道如果它适用于您的浏览器或出现错误。

评论


由于某种原因,添加!important会使声明为空。任何想法如何使用“重要”?

–密码
11月1日下午16:38

#12 楼

仔细查看答案,最明显,最直接的方法缺失了:使用document.write()写出所需的CSS块。 io / ssh33 / pen / zGjWga):

<style>
   @import url(http://fonts.googleapis.com/css?family=Open+Sans:800);
   .d, body{ font: 3vw 'Open Sans'; padding-top: 1em; }
   .d {
       text-align: center; background: #aaf;
       margin: auto; color: #fff; overflow: hidden; 
       width: 12em; height: 5em;
   }
</style>

<script>
   function w(s){document.write(s)}
   w("<style>.long-shadow { text-shadow: ");
   for(var i=0; i<449; i++) {
      if(i!= 0) w(","); w(i+"px "+i+"px #444");
   }
   w(";}</style>");
</script> 

<div class="d">
    <div class="long-shadow">Long Shadow<br> Short Code</div>
</div>


评论


很好,除非您需要在页面加载后创建CSS规则或正在使用XHTML。

– Tim Down
16年7月14日在9:47

#13 楼

function createCSSClass(selector, style, hoverstyle) 
{
    if (!document.styleSheets) 
    {
        return;
    }

    if (document.getElementsByTagName("head").length == 0) 
    {

        return;
    }
    var stylesheet;
    var mediaType;
    if (document.styleSheets.length > 0) 
    {
        for (i = 0; i < document.styleSheets.length; i++) 
        {
            if (document.styleSheets[i].disabled) 
            {
                continue;
            }
            var media = document.styleSheets[i].media;
            mediaType = typeof media;

            if (mediaType == "string") 
            {
                if (media == "" || (media.indexOf("screen") != -1)) 
                {
                    styleSheet = document.styleSheets[i];
                }
            } 
            else if (mediaType == "object") 
            {
                if (media.mediaText == "" || (media.mediaText.indexOf("screen") != -1)) 
                {
                    styleSheet = document.styleSheets[i];
                }
            }

            if (typeof styleSheet != "undefined") 
            {
                break;
            }
        }
    }

    if (typeof styleSheet == "undefined") {
        var styleSheetElement = document.createElement("style");
        styleSheetElement.type = "text/css";
        document.getElementsByTagName("head")[0].appendChild(styleSheetElement);
        for (i = 0; i < document.styleSheets.length; i++) {
            if (document.styleSheets[i].disabled) {
                continue;
            }
            styleSheet = document.styleSheets[i];
        }

        var media = styleSheet.media;
        mediaType = typeof media;
    }

    if (mediaType == "string") {
        for (i = 0; i < styleSheet.rules.length; i++) 
        {
            if (styleSheet.rules[i].selectorText.toLowerCase() == selector.toLowerCase()) 
            {
                styleSheet.rules[i].style.cssText = style;
                return;
            }
        }

        styleSheet.addRule(selector, style);
    }
    else if (mediaType == "object") 
    {
        for (i = 0; i < styleSheet.cssRules.length; i++) 
        {
            if (styleSheet.cssRules[i].selectorText.toLowerCase() == selector.toLowerCase()) 
            {
                styleSheet.cssRules[i].style.cssText = style;
                return;
            }
        }

        if (hoverstyle != null) 
        {
            styleSheet.insertRule(selector + "{" + style + "}", 0);
            styleSheet.insertRule(selector + ":hover{" + hoverstyle + "}", 1);
        }
        else 
        {
            styleSheet.insertRule(selector + "{" + style + "}", 0);
        }
    }
}





createCSSClass(".modalPopup  .header",
                                 " background-color: " + lightest + ";" +
                                  "height: 10%;" +
                                  "color: White;" +
                                  "line-height: 30px;" +
                                  "text-align: center;" +
                                  " width: 100%;" +
                                  "font-weight: bold; ", null);


评论


如果文档上没有当前样式表怎么办

– bluejayke
19年2月11日,下午1:57

#14 楼

这是我的模块化解决方案:您基本上在代码中的任何地方都可以执行:addNewStyle('body', 'color: ' + color1);,其中color1是定义的变量。

当您要“发布”当前CSS文件时,只需执行submitNewStyle()
,然后以后仍可以添加更多CSS。

如果要通过“媒体查询”添加它,则可以选择。
在“ addingNewStyles”之后,只需使用submitNewStyleWithMedia('min-width: 1280px');即可。


这对我的用例非常有用,因为我正在根据当前时间更改公共(而非我的)网站的CSS。我在使用“活动”脚本之前提交了一个CSS文件,然后提交了其余文件(使网站看起来有点像通过querySelector访问元素之前的样子)。

评论


我今天要尝试一下。让您知道这在我的用例中如何工作。手指交叉!!!

–lopezdp
2月7日下午14:34

#15 楼

为了搜索者的利益;如果您使用的是jQuery,则可以执行以下操作:

var currentOverride = $('#customoverridestyles');

if (currentOverride) {
 currentOverride.remove();
}

$('body').append("<style id=\"customoverridestyles\">body{background-color:pink;}</style>");


显然,您可以将内部CSS更改为所需的任何内容。有些人更喜欢纯JavaScript,但是它可以工作并且对于动态编写/覆盖样式非常健壮。