可维护 CSS 大量主题
Maintainable CSS for large number of themes
我必须为 Web 应用程序实现主题,用户可以在这些主题之间即时切换。设计师想要大约 20 种不同的字体颜色和背景颜色。有没有办法在不创建 20 个不同的 .css 文件的情况下做到这一点?那将是可维护性的噩梦。
我想 JavaScript 可能必须使用。我目前正计划将 .css 文件作为标记附加到 DOM,然后在用户更改主题时对颜色代码进行一些字符串替换。我希望找到更好的解决方案,因为这似乎是一个非常糟糕的 hack。
使用 SASS,您可以在 CSS 中使用变量,您只需在 1 个文件中更改它,它会使用更新的变量进行编译,您可能应该尝试一下。
干杯
CSS 预处理器总是在这里获胜。
我会避免使用带有 css 的单独样式表,而只是在一个地方定义所有颜色并加上良好的注释。它会因为 css 和那么多的配色方案而变得混乱。
即
/***
RED THEME
***/
.red-theme .button {}
.red-theme a {}
.red-theme #footer {}
/***
END RED THEME
***/
从广义上讲,我知道有两种方法可以在使用一个 css 源(可能需要也可能不需要多个文件)的同时更改网站的样式。
- 定义大量 classes
.blueBorder
、.redBorder
等并使用 JavaScript,根据需要在元素上添加和删除 classes。
- 或者定义classes并再次使用JavaScript,改变那些classes的定义。
可以混合使用这两种方法,但我不确定为什么要这样做。
这是使用第二种方法的JSFIDDLE。
我决定使用纯粹的 JavaScript 解决方案,而不是使用 jQuery,由于其选择器的强大功能,这会使编码更简单(我猜)。但是,我没有写其中的内容。函数 getCSSRule
,作者是 Patrick Hunlock,可以在 here 中找到。函数的每一行都有注释。但是,我删除了 Fiddle 中的注释只是因为包装问题。
函数 returns 指向 CSS 规则的指针,然后可以轻松地对其进行操作。例如:
// get a class rule (in production code check return value for valid result)
var r = getCSSRule('.primaryColor');
// change its definition
r.style.backgroundColor = "#f00";
所有分配给它们 class primaryColor
的元素的背景颜色将在上述 2 行执行时变为红色 (#f00)。没有其他要求。
注意 样式 sheet 中的节点名称与 CSS 规则不完全相同(backgroundColor
vs. background-color
)。我知道这里有很多人不喜欢 w3Schools.com 网站,但在寻找样式对象参考时,我就是在那里找到的。你可以找到它here
这是代码:
起始 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:
<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>
好东西,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";
};
兼容性注意事项
我在 IE11 和 Chrome 的当前版本中测试了这个具体示例。但是,自 2011 年左右以来,我在网站上部署了类似的代码,当时该网站支持的浏览器回到 IE7 或 IE8(不要'记得)并且没有人报告过问题。但我现在看到我确实为 Chrome 修补了 getCSSRule
函数。 (对于当前版本,我不必这样做。)这是补丁:
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?
我必须为 Web 应用程序实现主题,用户可以在这些主题之间即时切换。设计师想要大约 20 种不同的字体颜色和背景颜色。有没有办法在不创建 20 个不同的 .css 文件的情况下做到这一点?那将是可维护性的噩梦。
我想 JavaScript 可能必须使用。我目前正计划将 .css 文件作为标记附加到 DOM,然后在用户更改主题时对颜色代码进行一些字符串替换。我希望找到更好的解决方案,因为这似乎是一个非常糟糕的 hack。
使用 SASS,您可以在 CSS 中使用变量,您只需在 1 个文件中更改它,它会使用更新的变量进行编译,您可能应该尝试一下。
干杯
CSS 预处理器总是在这里获胜。
我会避免使用带有 css 的单独样式表,而只是在一个地方定义所有颜色并加上良好的注释。它会因为 css 和那么多的配色方案而变得混乱。
即
/***
RED THEME
***/
.red-theme .button {}
.red-theme a {}
.red-theme #footer {}
/***
END RED THEME
***/
从广义上讲,我知道有两种方法可以在使用一个 css 源(可能需要也可能不需要多个文件)的同时更改网站的样式。
- 定义大量 classes
.blueBorder
、.redBorder
等并使用 JavaScript,根据需要在元素上添加和删除 classes。 - 或者定义classes并再次使用JavaScript,改变那些classes的定义。
可以混合使用这两种方法,但我不确定为什么要这样做。
这是使用第二种方法的JSFIDDLE。
我决定使用纯粹的 JavaScript 解决方案,而不是使用 jQuery,由于其选择器的强大功能,这会使编码更简单(我猜)。但是,我没有写其中的内容。函数 getCSSRule
,作者是 Patrick Hunlock,可以在 here 中找到。函数的每一行都有注释。但是,我删除了 Fiddle 中的注释只是因为包装问题。
函数 returns 指向 CSS 规则的指针,然后可以轻松地对其进行操作。例如:
// get a class rule (in production code check return value for valid result)
var r = getCSSRule('.primaryColor');
// change its definition
r.style.backgroundColor = "#f00";
所有分配给它们 class primaryColor
的元素的背景颜色将在上述 2 行执行时变为红色 (#f00)。没有其他要求。
注意 样式 sheet 中的节点名称与 CSS 规则不完全相同(backgroundColor
vs. background-color
)。我知道这里有很多人不喜欢 w3Schools.com 网站,但在寻找样式对象参考时,我就是在那里找到的。你可以找到它here
这是代码:
起始 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:
<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>
好东西,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";
};
兼容性注意事项
我在 IE11 和 Chrome 的当前版本中测试了这个具体示例。但是,自 2011 年左右以来,我在网站上部署了类似的代码,当时该网站支持的浏览器回到 IE7 或 IE8(不要'记得)并且没有人报告过问题。但我现在看到我确实为 Chrome 修补了 getCSSRule
函数。 (对于当前版本,我不必这样做。)这是补丁:
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?