在 Stylus/Sass 中编写多个主题的设计模式?

Design patterns for writing multiple themes in Stylus/Sass?

我正在为需要支持多个 skins/themes 的网站编写样式表。例如,一个主题可能是以红色为主色的黑底白字,而另一个主题可能是以栗色为主色的黑底白字。

几乎所有来自一个主题的 CSS 都可以转换为另一个主题,但前景和背景颜色除外。

举个例子,假设我们有一个 div。 div 的大小和位置在主题之间是固定的,但颜色可能会改变。我们可以将其分成三个不同的 CSS 文件,如下所示:

/* main.css */
#box {
    position: absolute;
    top: 50px;
    left: 50px;
    width: 200px;
    height: 200px;
}

/* theme1.css */
#box {
    backround-color: red;
}

/* theme2.css */
#box {
    background-color: maroon
}

然后最终用户将加载 main.css 加上其中一个主题样式表。另一种设计是在 body 元素上放置一个 class,并使用选择器应用正确的颜色,所有这些都在一个 CSS 文件中。例如,

#box {
    position: absolute;
    top: 50px;
    left: 50px;
    width: 200px;
    height: 200px;
}

body.theme1 #box {
    backround-color: red;
}

body.theme2 #box {
    background-color: maroon
}

第二种方案的好处是HTTP请求较少。第一个选项的优点是用户需要从服务器加载较少的数据。当有许多不同的主题时,这一点尤其重要,并且(如在我的用例中)当内联背景图像显着增加 CSS 文件的权重时。

所以我的问题是,如何利用 CSS 预处理器(如 SASS 或 Stylus)的强大功能来创建多个 CSS 主题文件?

我设想的可能是这样的:

@theme(theme1) {
    $primaryColor: red;
}
@theme(theme2) {
    $primaryColor: maroon;
}

#box {
    position: absolute;
    top: 50px;
    left: 50px;
    width: 200px;
    height: 200px;

    background-color: $primaryColor;
}

这将依次生成上面第一个示例中列出的三个 CSS 文件。

有什么想法吗?这样的东西已经存在了吗?

我在 Sass 方面有更多经验,所以我的回答将主要集中在这一点上。至于手写笔,我知道的不够多,无法评论。

我认为你的第一个选项是最合适的。首先,动态包含第二个 'theme specific' .css 文件相对容易,而且就像你提到的那样,如果你最终会得到很多主题,它会保持样式精简,因为你有基本样式表然后是一个主题特定的样式表。

它也比您的第二个选项更容易扩展,因为您可以创建另一个主题并仅将新的 .css 文件添加到您的 server/app,而对于第二个选项,您必须重新上传整个文件。这不是什么大问题,但是如果你有很多主题,维护 Sass 文件可能会非常乏味,即使你将它们分成部分,然后 @import 'themes/theme-red' 或类似的东西进入主 Sass 编译前的样式表。

不幸的是 Sass 没有很多可用的服务器端编译选项,您可以在其中根据选定的主题动态生成样式。确实存在一个名为 phpSass 的编译器,但它现在似乎已基本失效,我不确定它会有多好。 LESS 更广泛地用于动态编译,因为如果您愿意考虑的话,服务器端和客户端编译都有更多选项。

我是这样完成的。制作三个 Stylus 文件:main.styltheme1.styltheme2.styl。然后如下图编辑他们的内容:

// theme1.styl
primaryColor = red
@require("main.styl")

// theme2.styl
primaryColor = maroon
@require("main.styl")

// main.styl
#box {
    top: 50px
    left: 50px
    width: 200px
    height: 200px
    background-color: primaryColor
}

那么你最终得到的是 theme1.csstheme2.css 包含所有应用程序的定义及其各自的主题。 (您将不再需要使用 main.css。)