简体   繁体   English

针对大量主题的可维护CSS

[英]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. 我希望找到一个更好的解决方案,因为这似乎是一个非常糟糕的黑客。

With SASS you can use variables in CSS, you'll just have to change it in 1 file and it compiles with updated variables you should probably try that. 使用SASS,您可以在CSS中使用变量,您只需要在1个文件中进行更改,并使用更新的变量进行编译,您应该尝试使用它。

Cheers 干杯

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源(可能需要或不需要多个文件)时,有两种方法可以改变站点的样式。

  1. Define lots of classes .blueBorder , .redBorder etc and using JavaScript, add and remove classes on elements as needed. 定义许多类.blueBorder.redBorder等并使用JavaScript,根据需要在元素上添加和删除类。
  2. Or define classes and using JavaScript again, change the definition of those classes. 或者定义类并再次使用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规则( backgroundColorbackground-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年左右以来,我在网站上部署了类似的代码,当时该网站支持浏览器返回IE7IE8 (不记得),没有人报告过这个问题。 But I see now that I did patch the getCSSRule function for Chrome . 但我现在看到我确实修补了ChromegetCSSRule函数。 (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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM