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

我需要在JavaScript中动态创建一个CSS样式表类,并将其分配给一些HTML元素,如- div,表,span, tr等,以及一些控件,如asp:Textbox,下拉列表和数据列表。

这可能吗?

要是有样品就好了。

374603 次浏览

这里有一个选项:

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

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属性。这并不总是理想的效果。

找到了一个更好的解决方案,适用于所有浏览器。
使用文档。样式表来添加或替换规则。公认的答案是简短和方便的,但这适用于IE8和更少。< / p >
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');

IE 9。现在可以加载文本文件并设置样式。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; }

有一个简单的jQuery插件,它允许生成CSS声明:jQuery-injectCSS

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

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

使用谷歌闭包:

你可以使用ccsom模块:

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

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

简单地说,这在“所有浏览器”(特别是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”属性,你可以用它来添加/删除规则。

以下是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;
}

查看答案,最明显和最直接的是缺少:使用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>

为了搜索者的利益;如果你正在使用jQuery,你可以做以下事情:

var currentOverride = $('#customoverridestyles');


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


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

显然,你可以改变内部css为任何你想要的。

有些人更喜欢纯JavaScript,但它可以工作,并且在动态编写/覆盖样式方面非常健壮。

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)

一个可以帮助你完成任务的有趣项目是js

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

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

Repl在线版本用于求值。

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

我在这里看了一些答案,我找不到任何自动添加一个新的样式表,如果没有,如果不是简单地修改一个现有的已经包含所需的样式,所以我做了一个新函数(应该跨所有浏览器工作,虽然没有测试,使用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");
}


};

然后在上面的函数中或其他任何地方添加这两个helper函数:

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

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

然后叫它:

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

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

以下是我的模块化解决方案:

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是定义变量。< / p > 当你想要“发布”当前CSS文件时,你只需执行submitNewStyle()
之后你还可以添加更多的CSS。< / p >

如果你想添加“媒体查询”,你有这个选项 在"addingNewStyles"之后你只需使用submitNewStyleWithMedia('min-width: 1280px');.


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

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

这个例子将一个cursor:pointer附加到每个buttoninputselect

document.body.appendChild(Object.assign(document.createElement("style"), {textContent: "select, button, input {cursor:pointer}"}))
这是我在Angular中工作的方法: 在HTML中,我有按钮与编程创建的CSS与特定的ID:

    <button [id]="'hoverbutton1'+item.key" [ngClass]="getHoverButtonClass()">
<mat-icon class="icon">open_in_new</mat-icon>
</button>

在typescript中,我创建了CSS,并将其分配给给定ID的特定元素:

addClasses(){
var style1 = document.createElement('style');
style1.innerHTML = '.hoverbutton'+this.item.key+' { display: none; }';
document.getElementsByTagName('head')[0].appendChild(style1);
}


getHoverButtonClass() {
return "hoverbutton"+this.item.key
}

通过这种方式,我可以创建尽可能多的CSS类,并将它们单独分配给元素。:)