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

时间:2012-01-05 15:22:30

标签: ruby-on-rails css css3 sass

所以我有一个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并在运行中更改它们并重新编译将会很不错。这是解决这个问题的最好方法吗?

4 个答案:

答案 0 :(得分:11)

3个简单的步骤:

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

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

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

  4. 不需要乱用动态编译等等。

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

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

答案 1 :(得分:8)

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

你在Rails中使用SASS-不要对抗当前的Railsy并让资产管道预编译所有的CSS。除非您尝试使用数百个主题进行CSSZenGarden之类的极端操作,或者每个主题数千行,否则我建议您将每个主题设置为拥有CSS类而不是它自己的文件。

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

您也可以只更改顶级元素上的类并自由使用继承和!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... */
       }

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

答案 2 :(得分:2)

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

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

答案 3 :(得分:1)

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

主题/ _whatever_theme.sass.erb

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

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