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

Posted

技术标签:

【中文标题】如何在 JavaScript 中动态创建 CSS 类并应用?【英文标题】:How to dynamically create CSS class in JavaScript and apply? 【发布时间】:2010-12-15 18:34:00 【问题描述】:

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

有可能吗?

如果有样品就好了。

【问题讨论】:

看看github.com/Box9/jss 另见***.com/questions/1212500/… 请注意,在某些情况下,您真正​​想要的可能不是完全创建一个 css 类并应用它,但您来到这里是因为您想一次添加多个样式,也许是因为它“更快”(更容易打字)。在这种情况下,请检查这个问题的答案,其中一些非常有用:***.com/questions/3968593/… 【参考方案1】:

这是一个选项:

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

【讨论】:

我的用例是一个小书签,它为 QA 目的突出显示某些元素。 很确定这会在 IE 8 及更低版本中导致未知的运行时错误。 我的用例是加载一个随机的谷歌网络字体,然后给 randomFont 类赋予 font-family :-) 另一个用例是您想要一个不依赖 CSS 文件的单个 JS 库。就我而言,我想要开箱即用的轻量级咆哮式警报弹出窗口。 我曾经需要同时高亮和取消高亮页面中的许多元素,对应于用户的选择。对所有元素应用和删除类是很慢的。因此,在我的 ajax 请求返回数据后的浏览器中,我为每个可能的选择创建了一个 css 类并将其应用于每个元素,为所有没有属性的类定义规则。一旦做出选择,重写规则本身就会以惊人的闪电速度更新页面上的所有元素。所以是的,有一个用例。【参考方案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-loop ifs 中添加“styleSheet.cssRules[i].selectorText &&”和“styleSheet.rules[i].selectorText &&”,因为它在 Chrome 中不起作用,显然有时 selectorText 是'未定义。 @w00t 您能否粘贴或编辑代码以使其正常工作? 我刚刚打开 Chrome(版本 34.0.1847.132)粘贴函数并执行它,但它不起作用:“TypeError:无法读取 null 的属性 'length'”。是不是从开发者控制台创建它不起作用? 事实证明,某些版本的 chrome(或 chromium)不允许在索引 0 上插入规则。这里是修复:styleSheet.insertRule(selector + "" + style + "", styleSheet.cssRules.length); @dnuske 我遇到了同样的问题。事实证明 styleSheet.cssRules 的计算结果为 null。我使用的修复方法是创建一个新变量 var styleSheetLength = styleSheet.cssRules ? styleSheet.cssRules.length : 0 并将其用法替换为函数的实现。【参考方案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;");

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

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;
    

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

关键一点是样式元素有一个“styleSheet”/“sheet”属性,您可以使用它来添加/删除规则。

【讨论】:

所以这会在每次创建类时创建一个新的“样式”元素?因此,如果我要在基于数据的 for 循环中创建 1000 多个类,这将需要应用 document.head.appendChild 1000 次? 对我来说 chrome style.sheet 和 style.styleSheet 不存在 它至少在 2022 年 1 月不再在 Chrome 中工作【参考方案4】:

有一个轻量级的 jQuery 插件可以生成 CSS 声明:jQuery-injectCSS

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

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

【讨论】:

类似于***.com/questions/1212500/…。【参考方案5】:

YUI 拥有迄今为止我见过的最好的stylesheet utility。我鼓励你去看看,但这里有一个味道:

// 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 就可以了。

// 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');
        
    )
);

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

.myClass  background:#F00; 

【讨论】:

【参考方案7】:

这是 Vishwanath 用 cmets 稍微改写的解决方案:

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】:

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

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

使用样式元素创建 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);

...

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

【讨论】:

【参考方案9】:

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

JSS 是一个 CSS 创作工具,它允许您使用 JavaScript 以声明性、无冲突和可重用的方式描述样式。它可以在浏览器、服务器端或在 Node 中构建时编译。

JSS 库允许您使用 .attach() 函数注入 DOM/head 部分。

Repl online version 用于评估。

进一步information on 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()

【讨论】:

【参考方案10】:

使用谷歌闭包:

你可以只使用 ccsom 模块:

goog.require('goog.cssom');
var css_node = goog.cssom.addCssText('.cssClass  color: #F00; ');

将css节点放入文档头部时,javascript代码尝试跨浏览器。

【讨论】:

【参考方案11】:

一个衬里,将一个或多个新的级联规则附加到文档。

此示例将cursor:pointer 附加到每个buttoninputselect

document.body.appendChild(Object.assign(document.createElement("style"), textContent: "select, button, input cursor:pointer"))

【讨论】:

【参考方案12】:

我在这里查看了一些答案,如果没有,我找不到任何自动添加新样式表的东西,如果不是简单地修改已经包含所需样式的现有样式表,所以我做了一个新功能(应该适用于所有浏览器,虽然未经测试,但使用 addRule,除此之外只有基本的原生 JavaScript,如果它有效,请告诉我):

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

;  

然后只需在上述函数内或其他任何地方添加这 2 个辅助函数:

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 Cs-s-ruleList 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;

(请注意,我在这两个中都使用了 for 循环而不是 .filter,因为 CSS 样式/规则列表类只有一个长度属性,而没有 .filter 方法。)

然后调用它:

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

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

【讨论】:

由于某种原因,添加 !important 会使声明为空。知道如何使用“重要”吗?【参考方案13】:

浏览了答案,但最明显和最直接的答案不见了:使用document.write() 写出您需要的一大段 CSS。

这是一个示例(在 codepen 上查看:http://codepen.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。【参考方案14】:

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

var currentOverride = $('#customoverridestyles');

if (currentOverride) 
 currentOverride.remove();


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

显然,您可以将内部 css 更改为您想要的任何内容。

感谢一些人更喜欢纯 JavaScript,但它可以工作并且对于动态编写/覆盖样式非常强大。

【讨论】:

【参考方案15】:
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);

【讨论】:

如果文档上没有当前样式表怎么办【参考方案16】:

这是我的模块化解决方案:

var final_style = document.createElement('style');
final_style.type = 'text/css';

function addNewStyle(selector, style)
  final_style.innerHTML += selector + ' ' + style + '  \n';
;

function submitNewStyle()
  document.getElementsByTagName('head')[0].appendChild(final_style);

  final_style = document.createElement('style');
  final_style.type = 'text/css';
;

function submitNewStyleWithMedia(mediaSelector)
  final_style.innerHTML = '@media(' + mediaSelector + ')\n' + final_style.innerHTML + '\n;';
    submitNewStyle();
;

您基本上在代码中的任何地方都可以:addNewStyle('body', 'color: ' + color1); ,其中 color1 是定义变量。

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

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


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

【讨论】:

我今天要试试这个。会让你知道这在我的用例中是如何工作的。手指交叉!!!!

以上是关于如何在 JavaScript 中动态创建 CSS 类并应用?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用css和javascript创建泪滴/水滴填充[重复]

如何在 wordpress 页面上包含带有自己的 css 和 javascript 的 php 页面? [关闭]

如何使用 css 和/或 javascript 动态更改样式

动态创建表格怎么用CSS设置表格属性 我是初学着,急用。我的代码如下 但是表格显示不出来

如何将一个对象数组中的所有项目从Javascript动态显示为HTML?

javascript 动态样式添加