How to Use Sass to Build One Project With Multiple Themes
The frontend-developer’s workflow has undergone big changes in recent years. More complexity, higher requirements and bigger projects move us toward new technologies such as preprocessors. Personally, I love my preprocessor workflow and wouldn't want to miss Sass for my projects these days - without it I would be a mess.
One situation in particular where Sass has helped me out is in creating a single solid frontend which can have different themes - changing colors, images or the fonts with ease. Today I’m going to describe my workflow, I hope you take something useful away from it.
Basic Structure
Here is the structure of an example project. You can use whatever partials you logically feel should be included. The key is in having a separate folder for themes and a new .scss
file for each theme.
Folder-Structure
1 |
|- _scss/ |
2 |
|-|- _base/ |
3 |
|-|-|- _config.scss |
4 |
|
5 |
|-|- _layouts/ |
6 |
|-|-|- _l-grid.scss |
7 |
|-|-|- _l-default.scss |
8 |
|
9 |
|-|- _modules/ |
10 |
|-|-|- _m-accordions.scss |
11 |
|-|-|- _m-teasers.scss |
12 |
|
13 |
|-|-_themes/ |
14 |
|-|-|- _light-theme/ |
15 |
|-|-|-|- light.scss |
16 |
|
17 |
|-|- application.scss |
Build the Base with a Main File
In the application.scss
file you import all your partials, ignoring the folder _themes/
at this point. This builds the foundation upon which we can create different themes.
1 |
@charset 'UTF-8'; |
2 |
|
3 |
// 1.Base |
4 |
@import '_base/_config.scss'; |
5 |
|
6 |
// 2.Layouts |
7 |
@import '_layouts/_l-grid', |
8 |
'_layouts/_l-default'; |
9 |
|
10 |
// 3.Modules |
11 |
@import '_modules/_m-accordions', |
12 |
'_modules/_m-teasers'; |
Configuration
Colors, Fonts and much more
Configuring your project is very important. Here variables come to the rescue, allowing us to set defaults then overwrite values at the theme level later on. Here you can see I've set some variables for colors, fonts and border settings.
For more detail on naming variables take a look at Jim Nielsen's Quick Tip: Name Your SASS Variables Modularly.
1 |
@charset "UTF-8"; |
2 |
|
3 |
// Colors |
4 |
$black: #000; |
5 |
$white: #fff; |
6 |
$red: #e2061c; |
7 |
$gray-light: #c9c8c8; |
8 |
$gray: #838282; |
9 |
$gray-dark: #333333; |
10 |
$blue: #253652; |
11 |
|
12 |
// Corp-Colors |
13 |
$corp-color: $blue !default; |
14 |
$corp-color-dark: darken($corp-color, 15%) !default; |
15 |
$corp-color-second: $red !default; |
16 |
$corp-color-second-dark: darken($corp-color-second, 15%) !default; |
17 |
|
18 |
// Font |
19 |
$base-font-size: 1.8 !default; |
20 |
$base-font-family: Helvetica, Arial, Sans-Serif !default; |
21 |
$base-font-color: $gray-dark !default; |
22 |
|
23 |
// Border |
24 |
$base-border-radius: 2px !default; |
25 |
$rounded-border-radius: 50% !default; |
26 |
$base-border-color: $gray !default; |
The key to this stage is in using the !default
flag after the variable declarations. Doing this allows you to overwrite them within the theme .scss
files; the !default
effectively says “use this value if it isn’t defined elsewhere”.
Background-Images
Very often developers don't create variables for images, instead writing urls directly within selectors. An approach I like is to remove all paths within partials and put them in the configuration file as variables. This will make your life easier and the project better maintainable.
1 |
// Images |
2 |
$sprite: '../images/base/sprite.png' !default; |
3 |
$colorbox-background: '../images/base/colorbox-background.png' !default; |
Example of a Basic Module
Here you can see some background variables in action. This is a modular partial for an accordion, making use of the global variable $sprite
but also setting and using a variable $accordion-bgcolor
which is specific to the module.
1 |
// 1.Config |
2 |
$accordion-bgcolor: $gray !default; |
3 |
|
4 |
// 2.Base |
5 |
.m-accordion { |
6 |
padding: 20px; |
7 |
background: $accordion-bgcolor; |
8 |
}
|
9 |
.m-accordion__trigger { |
10 |
background: url($sprite) no-repeat; |
11 |
}
|
How to Create a Theme
In your theme file (such as the _themes/_light-theme/light.scss
from the demo structure above) import the application.scss
which contains all the modules, layouts and so on. This is the basis for everything; with a theme we'll be placing a second layer over it. Nothing more. Once you’ve imported application.scss
add the same variables used earlier, but define values specific to this theme.
Using this technique, if we add new modules to the base of the project we will automatically (and harmlessly) compile them within all our themes.
1 |
@charset 'UTF-8'; |
2 |
|
3 |
// 1.Overwrite stuff |
4 |
$corp-color: $gray; |
5 |
$corp-color-darken: darken($corp-color, 10%); |
6 |
$corp-color-second: $blue; |
7 |
$corp-color-second-dark: darken($corp-color-second, 10%); |
8 |
|
9 |
$base-font-size: 1.6; |
10 |
$base-font-family: Droid Sans, Georgia, Arial; |
11 |
|
12 |
$base-border-radius: 0px; |
13 |
$base-border-color: $gray-light; |
14 |
|
15 |
// Images |
16 |
$sprite: '../images/light/sprite.png'; |
17 |
$colorbox-background: '../images/light/colorbox-background.png'; |
18 |
|
19 |
$accordion-bgcolor: $gray-light; |
20 |
|
21 |
// 2. Import basic theme |
22 |
@import '../../application'; |
Watching Multiple Files in Sass
The last step is to compile the Sass to CSS and get two different files for usage. We must compile application.scss
and the light.scss
. Using the command line you'd use something like:
1 |
sass --watch |
2 |
YOUR/PATH/application.scss:YOUR/CSSPATH/application.css |
3 |
YOUR/PATH/_themes/_light-theme/light.scss:YOUR/CSSPATH/light.css |
If you use an app, such as CodeKit, or Prepros App, compiling will be a more visual process.
Include the light.css
file in the head of your page and take a look at your freshened up website.
Conclusion
As you can see, it’s helpful and straightforward to have multiple theme files, all based upon one solid foundation. Feel free to ask questions, or give feedback and share your experiences with us in the comments section.