如何在 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
附加到每个button
、input
、select
。
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设置表格属性 我是初学着,急用。我的代码如下 但是表格显示不出来