[英]Maintainable CSS for large number of themes
I have to implement themes for a web app, which the user will be able to switch between on the fly. 我必须为Web应用程序实现主题,用户可以在运行中切换。 The designers want about 20 different font colors and background colors.
设计师需要大约20种不同的字体颜色和背景颜色。 Is there a way to do this without creating 20 different .css files?
有没有办法在不创建20个不同的.css文件的情况下执行此操作? That would be a maintainability nightmare.
这将成为可维护性的噩梦。
I'm thinking JavaScript will probably have to be used. 我认为可能必须使用JavaScript。 I'm currently planning on appending the .css file as a tag to the DOM, and then doing some string replacement on the color codes when the user changes the Theme.
我目前正计划将.css文件作为标记附加到DOM,然后在用户更改主题时对颜色代码进行一些字符串替换。 I was hoping to find a better solution, as this seems like a pretty bad hack.
我希望找到一个更好的解决方案,因为这似乎是一个非常糟糕的黑客。
Broadly speaking, I know of two ways to go about changing a site's style while using one css source (which may or not require multiple files). 从广义上讲,我知道在使用一个css源(可能需要或不需要多个文件)时,有两种方法可以改变站点的样式。
.blueBorder
, .redBorder
etc and using JavaScript, add and remove classes on elements as needed. .blueBorder
, .redBorder
等并使用JavaScript,根据需要在元素上添加和删除类。 It is possible to use a mixture of both approaches, though I'm not sure why one would want to do that. 可以使用两种方法的混合,但我不确定为什么要这样做。
Here's a JSFIDDLE using the 2nd approach. 这是使用第二种方法的JSFIDDLE 。
Rather than using jQuery, which would make the coding somewhat simpler (I guess) due to the power of its selectors, I decided to use a pure JavaScript solution. 由于其选择器的强大功能,我决定使用纯JavaScript解决方案,而不是使用jQuery,这会使编码更简单(我猜)。 The meat of which, however, I did not write.
然而,我没有写的肉。 The function
getCSSRule
, by Patrick Hunlock, can be found here . Patrick Hunlock的函数
getCSSRule
可以在这里找到。 Each line of the function is commented. 该功能的每一行都有注释。 However, I've removed the comments in the Fiddle only because of wrapping issues.
但是,由于包装问题,我删除了Fiddle中的注释。
The function returns a pointer to a CSS rule which then can be easily manipulated. 该函数返回一个CSS规则的指针,然后可以很容易地操作。 For example:
例如:
// get a class rule (in production code check return value for valid result)
var r = getCSSRule('.primaryColor');
// change its definition
r.style.backgroundColor = "#f00";
All elements which have the class primaryColor
assigned to them will have their background color change to red (#f00) at the point the 2 above lines execute. 具有分配给它们的类
primaryColor
所有元素将在上面的2行执行时将其背景颜色更改为红色(#f00)。 There is nothing else required. 没有其他要求。
NOTE the names of the nodes in the style sheet are not exactly the same as the CSS rule ( backgroundColor
vs. background-color
). 注意样式表中节点的名称与CSS规则(
backgroundColor
与background-color
)不完全相同。 I know a lot of folks here do not like w3Schools.com site, but when looking for a style object reference, that's where I found one. 我知道很多人不喜欢w3Schools.com网站,但在寻找样式对象参考时,我就找到了这个。 You can find it here
你可以在这里找到它
And here is the code: 以下是代码:
Starting CSS Styles: 启动CSS样式:
<style type="text/css">
#box1 {width: 50%; height: 200px; margin: 40px auto; padding-top: 20px;}
#box2 {width: 50%; height: 120px; margin: 20px auto 20px; padding: 10px;}
.primaryColor {background-color: #f00;}
.primaryBorder {border: 10px solid #000;}
.secondaryColor {background-color: #ff0;}
.secondaryBorder {border: 5px solid #fff;}
.t {color: #f00;}
</style>
HTML: HTML:
<div id="box1" class="primaryColor primaryBorder">
<div id="box2" class="secondaryColor secondaryBorder"><p class="t">Theme Demonstration</p>
</div>
</div>
<form style="margin: 40px auto; width:50%">
<div role="radio" style="text-align:center" aria-checked="false">
<input type="radio" name="theme" CHECKED value="theme1" onClick="setThemeOne()" >Theme 1
<input type="radio" name="theme" value="theme2" onClick="setThemeTwo()" >Theme 2
<input type="radio" name="theme" value="theme3" onClick="setThemeThree()">Theme 3
</div>
</form>
And the good stuff, JavaScript: 好的东西,JavaScript:
function getCSSRule(ruleName, deleteFlag) {
ruleName=ruleName.toLowerCase();
if (document.styleSheets) {
for (var i=0; i<document.styleSheets.length; i++) {
var styleSheet=document.styleSheets[i];
var ii=0;
var cssRule=false;
do {
if (styleSheet.cssRules) {
cssRule = styleSheet.cssRules[ii];
} else {
cssRule = styleSheet.rules[ii];
}
if (cssRule) {
if (cssRule.selectorText.toLowerCase()==ruleName) {
if (deleteFlag=='delete') {
if (styleSheet.cssRules) {
styleSheet.deleteRule(ii);
} else {
styleSheet.removeRule(ii);
}
return true;
} else {
return cssRule;
}
}
}
ii++;
} while (cssRule)
}
}
return false;
}
function setThemeOne() {
var r = getCSSRule('.primaryColor');
r.style.backgroundColor = "#f00";
r = getCSSRule('.primaryBorder');
r.style.border = "10px solid #000;";
r = getCSSRule('.secondaryColor');
r.style.backgroundColor = "#ff0";
r = getCSSRule('.secondaryBorder');
r.style.border = "5px solid #fff";
r = getCSSRule('.t');
r.style.color = "#000";
};
function setThemeTwo() {
var r = getCSSRule('.primaryColor');
r.style.backgroundColor = "#ff0";
r = getCSSRule('.primaryBorder');
r.style.border = "10px solid #ccc;";
r = getCSSRule('.secondaryColor');
r.style.backgroundColor = "#f00";
r = getCSSRule('.secondaryBorder');
r.style.border = "5px solid #000";
r = getCSSRule('.t');
r.style.color = "#ccc";
};
function setThemeThree() {
var r = getCSSRule('.primaryColor');
r.style.backgroundColor = "#ccc";
r = getCSSRule('.primaryBorder');
r.style.border = "10px solid #000;";
r = getCSSRule('.secondaryColor');
r.style.backgroundColor = "#000";
r = getCSSRule('.secondaryBorder');
r.style.border = "5px solid #fff";
r = getCSSRule('.t');
r.style.color = "#fff";
};
Note about compatibility 关于兼容性的注意
This specific example I've tested in IE11 and current version of Chrome . 这个具体的例子我在IE11和当前版本的Chrome中测试过。 However, I've had similar code deployed on a site since about 2011 and at that time the site supported browsers back to IE7 or IE8 (don't recall) and no one ever reported an issue.
但是,自2011年左右以来,我在网站上部署了类似的代码,当时该网站支持浏览器返回IE7或IE8 (不记得),没有人报告过这个问题。 But I see now that I did patch the
getCSSRule
function for Chrome . 但我现在看到我确实修补了Chrome的
getCSSRule
函数。 (I did not have to do that for the current version.) Here's the patch: (我没有为当前版本做到这一点。)这是补丁:
if (cssRule){ //If we found a rule...
// [KT] 04/24/2012 - added condition to check for undefined selector for Chrome
if ((cssRule.selectorText != undefined) && cssRule.selectorText.toLowerCase()==ruleName)){//match rule Name?
CSS preprocessors always win here. CSS预处理器总是赢得这里。
I would avoid a separate stylesheet with css and just define all your colours in one place with good commenting. 我会避免使用带有CSS的单独样式表,只需在一个地方定义所有颜色并进行良好的评论。 Its going to get messy with css and that amount of colour schemes.
它会变得混乱css和大量的配色方案。 ie
即
/***
RED THEME
***/
.red-theme .button {}
.red-theme a {}
.red-theme #footer {}
/***
END RED THEME
***/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.