User theme switching with SASS - Ruby on Rails

后端 未结 4 542
执笔经年
执笔经年 2021-02-04 13:45

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. H

4条回答
  •  栀梦
    栀梦 (楼主)
    2021-02-04 14:03

    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.

提交回复
热议问题