使用SASS进行用户主题切换 – Ruby on Rails

所以我有一个rails管理系统,允许用户选择一个主题,基本上是一组SASS颜色变量,它们将使用新颜色重新编译application.css.scss。 当用户从下拉列表中选择并提交时,如何才能更改此更改? 我读了一些关于缓存和重新编译的问题,但我不完全清楚如何设置它。

目前我有..

application.css.scss

@import "themes/whatever_theme"; @import "common"; @import "reset"; @import "base"; 

主题/ _whatever_theme

 $theme_sprite_path: '/images/sprite_theme_name.png'; $main_color:#009DDD; $secondary_color:#b3d929; $light_background:#f2f2f2; $border_line:#e6e6e6; $off_white:#f9f9f9; $white:#ffffff; $font_body:#565b59; $font_headers:#363a36; 

假设我有5个不同的主题,用户将在它们之间切换,为Rails中的每个主题设置变量名称然后将它们传递给SASS并在运行中更改它们并重新编译将会很不错。 这是最好的解决方法吗?

3个简单步骤:

  1. 部署时将所有主题编译为不同的文件。 这将负责时间戳,压缩等。

  2. 使用默认主题渲染页面。

  3. 使用javascript加载备用主题CSS。

无需乱搞动态编译等等。

要动态加载CSS,您可以使用以下内容:

 function loadCSS(url) { var cssfile = document.createElement("link"); cssfile.setAttribute("rel", "stylesheet"); cssfile.setAttribute("type", "text/css"); cssfile.setAttribute("href", url); } 

塞尔吉奥的答案是有效的,但省略了时髦的细节,我使用了一种稍微不同的方法。

你在Rails中使用SASS-不要与当前战斗,Railsy并让资产管道预编译你所有的CSS。 除非你试图做一些像CSSZenGarden那样有着数百个主题的东西 ,或者每个主题都是成千上万行,我建议把每个主题设置为它自己的CSS类,而不是它自己的文件。

  • 渲染的application.css文件中的1kb额外CSS不会让您的用户陷入困境
  • 使用JQuery切换主题类很简单: $(".ThemedElement").removeClass([all your themes]).addClass("MyLittlePonyTheme");
  • 如上所述,您必须使用ThemedElement类标记要更新的元素

您也可以只更改顶级元素上的类并自由使用inheritance和!important声明,尽管我发现另一种方法更易于维护。

如果您认为可以使用类而不是文件来管理主题,那么我们将使用SASS生成它们。 SASS不支持json样式对象,所以我们必须回过头来设置一堆带有主题属性的并行数组。 然后我们遍历每个主题,将动态属性替换为自动生成的主题类,然后你就开始了比赛:

themes.css.scss

 @import "global.css.scss"; /* iterate over each theme and create a CSS class with the theme's properties */ @for $i from 1 through 4{ /* here are the names and dynamic properties for each theme class */ $name: nth(("DefaultTheme", "MyLittlePonyTheme", "BaconTheme", "MySpaceTheme" ), $i); $image: nth(("/assets/themes/bg_1.png", "/assets/themes/bg_2.png", "/assets/themes/bg_3.png", "/assets/themes/bg_4.png" ), $i); $primary: nth((#7ca8cb, #3c6911, #d25d3a, #c20d2c ), $i); $font: nth((Rosario, Helvetica, Comic Sans, WingDings ), $i); /* Now we write our Theme CSS and substitute our properties when desired */ .#{$name}{ &.Picker{ background-image:url($image); } color: $primary; .BigInput, h1{ color: $primary; font-family: $font, sans-serif !important; } .Frame{ background-image:url($image); } .Blank:hover{ background-color:mix('#FFF', $primary, 90%) !important; } .BigButton{ background-color:$primary; @include box-shadow(0,0,10px, $primary); } /* and so on... */ } 

这有点像黑客,但它对我们很有帮助。 如果你的主题很复杂,或者你的主题太多,那么维护就会变得更加痛苦。

一种选择是在application.css之后简单地加载一组自定义css规则(您的主题),并让您的主题覆盖application.css中的默认颜色。 您可以添加一个数据库列“theme”并动态加载带有此名称的css。

SASS不是为动态编译动态数据而设计的。 如果你想要动态css处理,你可以添加一个名为“custom_css”的控制器方法,并使其响应css格式并使用内联变量动态加载它,但我认为SASS根本不用于它。

我相信你可以使用erb在sass中内联变量。 我不是积极的,但我认为它看起来像这样:

主题/ _whatever_theme.sass.erb

 $theme_sprite_path: '<%= Theme.sprite_path %>'; $main_color: <%= Theme.main_color %>; $secondary_color: <%= Theme.secondary_color %>; 

应为每个页面加载动态创建这些内容。 我不确定缓存在这里是如何工作的。