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
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.
$(".ThemedElement").removeClass([all your themes]).addClass("MyLittlePonyTheme");
ThemedElement
classYou 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.