This post outlines a way to use Sass, Compass, and Grunt to maintain stylesheets for a WordPress parent and child theme.
Sass is useful for many reasons, but for our purposes, the two most helpful features are partials and variables. We'll also take advantage of the importPath
setting of Compass and Grunt.
Comments and improvements are always welcome.
Create a new Compass project in your theme and style away. When you're finished, your theme directory (called parent
here) might look something like this:
parent/
├── css/
└── sass/
├── _base.scss
├── _media.scss
├── _typography.scss
└── theme.scss
and theme.scss
might look like:
@import "base";
@import "typography";
@import "media";
etc.
so that compiling theme.scss
results in theme.css
.
Suppose that the main difference between our parent and child theme is the color scheme. We can start setting this up by, first, creating a new directory inside parent/sass
. Call it parent-only
for this example.
In the parent-only
directory, create a partial to store the parent theme's color scheme. Make sure to use variables to define the colors. Then, of course, use the variables throughout your theme.
Our directory tree now looks like:
parent/
├── css/
└── sass/
├── parent-only/
└── _colors.scss
├── _base.scss
├── _media.scss
├── _typography.scss
└── theme.scss
_colors.scss
might look like:
$primary: #ff0000;
$secondary: #0000ff;
$dark: #444444;
etc.
and theme.scss
would now look like:
@import "base";
@import "colors";
@import "typography";
@import "media";
etc.
Create a directory in your child theme to hold Sass partials that will be specific to the child theme, as well as a directory for the compiled CSS. This results in a directory tree of:
parent/
├── css/
└── sass/
├── parent-only/
└── _colors.scss
├── _base.scss
├── _media.scss
├── _typography.scss
└── theme.scss
child/
├── css/
└── sass/
Next, create a _colors.scss
file in our child theme's sass
directory. This is where we specify the child theme's color scheme, using the same variables as the _colors.scss
in the parent:
$primary: #ff00ff;
$secondary: #00ffff;
$dark: #444444;
etc.
giving us the directory tree:
parent/
├── css/
└── sass/
├── parent-only/
└── _colors.scss
├── _base.scss
├── _media.scss
├── _typography.scss
└── theme.scss
child/
├── css/
└── sass/
└── _colors.scss
For this method to work, we need to run Compass twice, with different settings each time. Grunt can help with that.
The Grunt website provides documentation on how to set up Grunt. You'll also need the grunt-contrib-compass plugin.
Once you've done that, create a task (called compass
here) in your Gruntfile.js
that looks like this:
compass: {
options: {
sassDir: 'sass',
javascriptsDir: 'javascripts',
fontsDir: 'fonts',
outputStyle: 'compressed',
environment: 'production'
},
parent: {
options: {
importPath: 'sass/parent-only',
httpPath: '/wp-content/themes/parent/',
cssDir: 'css/',
}
},
child: {
options: {
importPath: '../child/sass/',
cssDir: '../child/css/',
httpPath: '/wp-content/themes/child/'
}
}
},
Taking each of the main sections in turn:
-
The
options
section defines settings common to the parent and child themes. Obviously, you can changeoutputStyle
orenvironment
as preferred, or add other options. -
The
parent
section defines parent theme-specific settings. The most important of these isimportPath
. It tells Compass to search in the specified directory when looking for an@import
ed file if it can't find that file in thesassDir
. -
The
child
section defines the same settings, but with key differences. First, theimportPath
jumps into thesass
directory of the child theme that we created earlier. Second, thecssDir
is set to send our compiled CSS into the child theme.
So, running the compass
task will compile theme.scss
twice, resulting in wp-content/themes/parent/css/theme.css
and wp-content/themes/child/css/theme.css
.
importPath
is where the magic happens. When Compass tries to compile theme.scss
, it won't find _colors.scss
in the sass
directory. But importPath
sends Compass to the parent or child theme and the _colors.scss
file we created specifically for each.
-
We can change
parent/sass/parent-only/_colors.scss
and have it apply only to the parent theme. -
We can change
child/sass/_colors.scss
and have it apply only to the child theme. -
We can change
parent/sass/_typography.scss
, or_media.scss
, or any other shared Sass file, and have the changes apply to both themes.
Thanks Dave :) this has made my day.
It's exactly what i was looking for and has given me loads of exiting things to explore with Grunt which i haven't used before. I've added a task with grunt-contrib-watch as well so it can wait for changes to compile automatically.