Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

User theme switching with SASS - Ruby on Rails

So I have an rails admin system that will allow a user to choose a theme, basically a set of SASS color variables that will recompile application.css.scss with the new colors. How would be the best way of going about changing this when the user selects from a drop down and submits? I read some up on some problems with caching and recompiling but I'm not totally clear how to set it up.

Currently I have..

application.css.scss

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

themes/_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;

Say I have 5 different themes the user will switch between, it would be nice to set variable names for each theme in Rails then pass these down to SASS and change them on the fly and recompile. Is this the best way to go about this?

like image 558
olliekav Avatar asked Jan 05 '12 15:01

olliekav


1 Answers

Sergio's answer is valid, but omits the sassy details and I'd used a slightly different approach.

You're using SASS in Rails- don't fight the current, be Railsy and let the asset pipeline precompile all your CSS. Unless you're trying to do something extreme like CSSZenGarden with hundreds of themes, or each theme is thousands of lines I'd recommend setting each theme as it's own CSS class rather than it's own file.

  • 1kb of extra CSS in the rendered application.css file won't bog down your users
  • It's straightforward to switch theme classes with JQuery: $(".ThemedElement").removeClass([all your themes]).addClass("MyLittlePonyTheme");
  • As implied, you will have to tag the elements you want the update with the ThemedElement class

You could alternatively just change the class on your top level element and make liberal use of inheritance and the !important declaration, although I find the other approach more maintainable.

If you think you can manage your themes with classes rather than files, here's how we generate them with SASS. SASS doesn't support json style objects, so we have to reach way back and set up a bunch of parallel arrays with the theme properties. Then we iterate over each theme, substitute the dynamic properties into the auto generated theme class, and you're off to the races:

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... */
       }

It's a bit of a hack, but it's served us really well. If your themes are uber complicated or you have too many of them it gets more painful to maintain.

like image 94
RSG Avatar answered Sep 21 '22 14:09

RSG