I want to create different css-themes for a WordPress theme by using theme setup files. The setup (simplified) would be as following:
/themes/_theme1.scss
/themes/_theme2.scss
/components/_file1.scss
/components/_file2.scss
/theme.scss
The idea is to enable easy theming by adding a class to the body of the document like .theme-theme1
or .theme-theme2
. In the files _theme#.scss
I want to define variables like text colour, font sizes and so on. In _file#.scss
the actual styles are defined.
My question now is, how to iterate over the theme setup files while filling up the files.scss.
Sample idea, Background colour:
body {
###foreach themefile###
&.theme# {
background-color: $background-color;
}
###/foreach###
}
I know how to do this with only one theme available in the resulting CSS file, but I want to make ALL themes available in the resulting CSS. Feel free to ask more details as I am not sure if I explain me right.
Is there a way to create this stylesheet via some kind of foreach loops through variables in theme files or does it have to be done with extra scss-rules per theme file?
This is somewhat possible using a combo of @import
with a @mixin
to generate the styles. This method should produce minimal repeated code.
Here's how we'll setup the files.
- scss
- themes
- _theme1.scss
- _theme2.scss
- _theme.scss
- styles.scss
The _
prefix on some of the files prevent them from being compiled into CSS to keep our build nice and clean. Now let's go through the contents of the files:
_theme1.scss
$theme-name: 'theme1';
$primary-color: red;
$primary-font-size: 24px;
_theme2.scss
$theme-name: 'theme2';
$primary-color: blue;
$primary-font-size: 12px;
This is an oversimplified example but should give the basic idea. Each theme file will contain only variables.
_theme.scss
@mixin themestyle() {
body.#{$theme-name} {
p {
color: $primary-color;
font-size: $primary-font-size;
}
.bordered {
border: 3px solid $primary-color;
}
}
}
The themestyle
mixin will contain all the styles for each theme, using the variables from the /themes/_theme*.scss
files. The body.#{$theme-name}
will create a selector like body.theme1
or body.theme2
, depending on the current value of the $theme-name
variable.
In this demo I'm styling on a p
tag but this could easily be extended to all elements/selectors for your site. The important thing to remember is all styles need to be inside the body.#{$theme-name}
selector.
Now the final, and least DRY part. The styles.scss
file will import each theme file then call the themestyle
mixin to generate the styles for each theme.
styles.scss
@import 'themes/theme';
/* Theme 1 Styles */
@import 'themes/theme1';
@include themestyles();
/* Theme 2 Styles */
@import 'themes/theme2';
@include themestyles();
The repeated @import/@include
is required because it's not possible to @import
within a loop or mixin, or this could be optimized a bit more.
Once styles.scss
is compiled the output will be:
/* Theme 1 Styles */
body.theme1 p {
color: red;
font-size: 24px; }
body.theme1 .bordered {
border: 3px solid red; }
/* Theme 2 Styles */
body.theme2 p {
color: blue;
font-size: 12px; }
body.theme2 .bordered {
border: 3px solid blue; }
These themes can now be implemented by adding a class to the body
tag, like <body class="theme1">
or <body class="theme1">
.
Here's a Cloud9 project showing the setup.