如何在JavaScript中动态创建CSS类并应用?

Him*_*dri 280 javascript css stylesheet

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

可能吗?

一个样本会很好.

I.d*_*ies 371

虽然我不确定你为什么要用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';
Run Code Online (Sandbox Code Playgroud)

  • 很确定这会导致IE 8中的未知运行时错误. (25认同)
  • 另一个用例是你想要一个没有CSS文件依赖的单个JS库.在我的情况下,我想要开箱即用的轻量级咆哮式警报弹出窗口. (24认同)
  • 我的用例是一个书签,它突出显示了用于QA目的的某些元素. (8认同)
  • 我曾经需要根据用户的选择同时突出显示和取消突出显示页面中的许多元素。对所有元素应用和删除类非常缓慢。因此,在我的 ajax 请求返回数据后,在浏览器中,我为每个可能的选择创建一个 css 类,并将其应用到每个元素,为所有没有属性的类定义规则。一旦做出选择,重写规则本身就会以惊人的**闪电般的速度**更新页面上的所有元素。是的,有一个用例。 (5认同)
  • 我正在做类似 w00t 的事情。我正在开发一个交互式 html5 应用程序,它将在画布上书写,我想让我的用户从多种字体中进行选择。我计划创建一个后端,在其中上传字体数据,并且每当加载程序时,对 Web 服务的一点调用都会带来字体并添加它们,而不是使用包含所有字体的冗长 css (2认同)
  • 我知道这是一篇旧文章,但要更新它, `document.getElementsByTagName('head')[0].appendChild(style);` 应该是 `document.head.appendChild(style)`。 (2认同)

Vis*_*ath 109

找到了一个更好的解决方案,适用于所有浏览器.
使用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);
  }
}
Run Code Online (Sandbox Code Playgroud)

功能如下使用.

createCSSSelector('.mycssclass', 'display:none');
Run Code Online (Sandbox Code Playgroud)

请注意,即使函数名称是createClass,它实际上也会创建一个选择器.所以别忘了在你的班级名字之前加上.(句号).无需提及您也可以使用此功能创建其他选择器.

  • 确认使用IE8.我必须在mediaType for-loop ifs中添加"styleSheet.cssRules [i] .selectorText &&"和"styleSheet.rules [i] .selectorText &&",因为它在Chrome中不起作用,显然有时候selectorText不是没有定义. (2认同)
  • @dnuske 我遇到了同样的问题。结果是 styleSheet.cssRules 的计算结果为 null。我使用的修复方法是创建一个新变量 `var styleSheetLength = styleSheet.cssRules ?styleSheet.cssRules.length : 0` 并将其用法替换为函数的实现。 (2认同)

小智 26

简短的回答,这是"兼容所有浏览器"(特别是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;");
Run Code Online (Sandbox Code Playgroud)

最后一位将类应用于元素:

function applyClass(name,element,doRemove){
    if(typeof element.valueOf() == "string"){
        element = document.getElementById(element);
    }
    if(!element) return;
    if(doRemove){
        element.className = element.className.replace(new RegExp("\\b" + name + "\\b","g"));
    }else{      
        element.className = element.className + " " + name;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

关键的一点是,样式元素具有"styleSheet"/"sheet"属性,您可以使用它来添加/删除规则.


Yak*_*ako 17

有一个轻量级的jQuery插件,允许生成CSS声明:jQuery-injectCSS

实际上,它使用JSS(JSON描述的CSS),但是为了生成动态css样式表,它很容易处理.

$.injectCSS({
    "#test": {
        height: 123
    }
});
Run Code Online (Sandbox Code Playgroud)


NVR*_*VRM 9

在一份衬垫中,将一个或多个新的级联规则附加到文档中。

此示例将 a 附加cursor:pointer到每个button, input, select

document.body.appendChild(Object.assign(document.createElement("style"), {textContent: "select, button, input {cursor:pointer}"}))
Run Code Online (Sandbox Code Playgroud)


Rus*_*ett 7

到目前为止,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);
Run Code Online (Sandbox Code Playgroud)

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


小智 5

从IE 9开始.您现在可以加载文本文件并设置style.innerHTML属性.所以基本上你现在可以通过ajax加载一个css文件(然后得到回调),然后在这样的样式标签里面设置文本.

这适用于其他浏览器,不知道有多远.但只要你不需要支持IE8那么它就可以了.

// 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');
        }
    })
});
Run Code Online (Sandbox Code Playgroud)

然后你可以让它拉出像myCss.css这样的外部文件

.myClass { background:#F00; }
Run Code Online (Sandbox Code Playgroud)


use*_*905 5

这是 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;
    }
Run Code Online (Sandbox Code Playgroud)


Raz*_*aul 5

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

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

  • 使用 Style Element 创建 CSS 部分
  • 使用样式元素的 ID 以便我们可以更新 CSS

……

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);
}
Run Code Online (Sandbox Code Playgroud)

...

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