Using Gulp for managing themes

Recently at The Hideout we have been working on a large project whereby we had to completely refresh the online look and feel of multiple restaurants owned by a single group. Each restaurant has their own look and feel and that needed to be illustrated, whilst keeping the sites consistent in layout in order to link back to the group brand. Before beginning the development of the sites from the designs, we needed a solid game plan to ensure the foundations were set for us to overcome the obstacles of this project.

The Hideout

The challenge

The challenge we discovered is that we were going to be using the same website for five or more restaurants, each with their own brand guidelines. The guidelines outline their colour palette, typefaces, and use of the logo. Each website needs to use the same mark-up and share the majority of the CSS, but be able to change the colours for every element, the heading/body typography and their font sizes as they will differ in base size. The client also has growth plans so the code needs to be written to enable us to duplicate the base layout styles but modify the theme with relative ease, ensuring value for money moving forwards.

The majority of web projects at The Hideout I find myself using the compass menu bar application for quick compiling of sass files into a browser compatible CSS document. For this project I needed to be able to compile the themes into separate CSS files of their own, something that compass could not handle. Instead I opted to use Gulp, which is a popular task runner for web development.

 

The Hideout

A task runner?

This is a piece of kit used for automation of repetitive tasks like minification, compilation, unit testing, linting etc. Gulp is one type of task runner, and uses a JavaScript file to run a set of tasks that can be piped onto each other which need to be completed regularly. Perfect for SASS, which normally needs to be compiled into plain CSS after every save so that the changes can be seen in the browser. It’s completely configurable too, you decide what node packages are included, perfect for my custom requirements for compilation.

javascript-code
bokeh-developer

Gulp requirements

For Gulp to work properly, you need to install node on your machine and npm (node packet manager). This is where the Gulp packages are installed. I won’t go into much more detail on this, but Travis Maynard has a thorough article on Getting started with Gulp which I found very handy. Once you have them installed on your machine, you need to create a gulpfile.js in the root of your project directory. Here the Gulp packages are included and the functions for running the tasks are written.

The gulpfile

Here I’ll go through the different parts of the gulpfile. It’s a relatively small document with only three methods; sass-theme, sass and watch. Before anything can function, we need to include Gulp, and any other plugins to the gulpfile at the top of the document:

// Include gulp
var gulp    = require('gulp');

// Include other required plugins
var sass    = require('gulp-sass'),
sourcemaps  = require('gulp-sourcemaps');

The sass-theme method is being used to loop every theme sass file within the /sass/themes directory, check for errors, compile them and output them in css/themes/.

// Loop sass theme files and output separately.
gulp.task('sass-theme', function () {
return gulp.src('./assets/sass/themes/*.scss')
	.pipe(sourcemaps.init())
	.pipe(sass({
	outputStyle: 'expanded',
	}))
	.on('error', sass.logError)
	.pipe(sourcemaps.write())
	.pipe(gulp.dest('./assets/css/themes'))
});

The sass method does the same, but compiles the base theme style main.scss only.

// Compile main sass file
gulp.task('sass', function () {
return gulp.src([
		'./assets/sass/main.scss',
	])
	.pipe(sourcemaps.init())
	.pipe(sass({
		outputStyle: 'expanded',
	}))
	.on('error', sass.logError)
	.pipe(sourcemaps.write())
	.pipe(gulp.dest('./assets/css'))
});

The watch method does what it says – it watches the sass files and runs the two sass methods anytime a file changes.

// Watch Files For Changes
gulp.task('watch', function() {
	gulp.watch('./assets/sass/**/*.scss', ['sass', 'sass-theme']);
});

To run the gulpfile, I point my terminal to the project folder and type gulp watch. This continues to run in the background until I close the terminal window.

The Hideout

Folder structure

Now that Gulp is installed and configured correctly, its time to get the folder structure organised for the sass partials and theme files.

Here’s an example of the structure I used for this project. Each .scss partial will be imported into the main.scss file at the root of the /sass directory. The only exception to this is the /themes subfolder, which will include only variables overrides, font imports and any restaurant specific styles to be applied. More on this in a while. It’s important here that the themes are in a folder of their own.

/sass
	|_ /base
		| _resets.scss
		| _base.scss
		| _mixins.scss
	
	|_ /components
		| _button.scss
		| _lists.scss
		| _sub-nav.scss
		| _forms.scss
		| _another-component.scss
	
	|_ /layout
		| _header.scss
		| _footer.scss
	
	|_ /pages
		| _homepage.scss
		| _another-page.scss
		| _subpage.scss
	
	|_ /themes
		| restaurant-1.scss
		| restaurant-2.scss
		| restaurant-3.scs
		
		
main.scss
themeConfig.scss

Note: each file has an underscore at the start of the file name to indicate that it is a partial file and that it should not be generated into a CSS file of its own (anything that will be being imported into another sass file). The restaurant files do not have this because we DO want them to be generated into a file of their own.

Base main.scss file

// 1. Mixins and variables
@import 'base/mixins',
		'base/variables';

// 2. Core theme config
@import 'themeBase';

// 3. Base styles
@import 'base/resets',
		'base/slider',
		'base/base';

// 4. Layout files
@import 'layout/header',
		'layout/footer';

// 5. Components
@import 'components/button',
		'components/forms',
		'components/social-media',
		'components/sub-nav',
		'components/tables',
		'components/typography',

// 5. Page specific styles
@import 'pages/homepage',
		'pages/sitemap',
		'pages/subpage';

I’ve included all relevant files in their required order – sass mixins, resets & base styles at the top, followed by layout styles for the header and footer, components and then page specific styles and overrides at the bottom. The one file I haven’t mentioned yet is themeBase.scss. This is the location for our core config file for the variables which we will be duplicating any time we need to create a stylesheet with new theme styles.

developer-portrait

Introducing !default

the !default feature of sass was very useful when defining variables in the theme config file. Edwin Morris explains the feature very well:

You can assign to variables if they aren’t already assigned by adding the !default flag to the end of the value. This means that if the variable has already been assigned to, it won’t be re-assigned, but if it doesn’t have a value yet, it will be given one.

Theme Config

This is exactly what was produced in the config file, a list of variables, which reference something within any of the sass files. We can change it’s colour, background colour, font size and so on. It’s like a traditional variable, but if we define the same variable somewhere else without the !default tag, like in a restaurant specific file, when compiled it will choose the new variable over the !default. Here’s an example use case:

// Define our primary styles
$primaryColour:#002f24 !default;
$secondaryColour:#002e21 !default;
$colorDark:#000000 !default;
$baseFontSize: 16px !default;

// in our restaurant theme file
$primaryColour:#ffffff;
$secondaryColour:#000000;
$colorDark:#090909;
$baseFontSize: 14px;

This may seem like a workaround method, but if the config file is defined with enough detail, any developer who has been tasked with adding the styles for a new restaurant should only need to duplicate and access one file in order to create the new theme. The alternate method would be to copy up the SASS, go into each file and modify the styles individually. Not only will this be a more time consuming process, but also it will create duplicates of the same set of files, one for each restaurant. This will become difficult to maintain in the future if there is a bug that needs to be fixed across every restaurant site.

Example restaurant theme

Here’s a final example of the layout of the single restaurant theme. All variable overrides appear at the top of the document, and the main styles are imported at the very bottom:

/* DOCUMENT INFORMATION
- Document: Core Theme
- Version:  1.0.0
- Author:   The Hideout
*/

// Theme specific variables and styles go in this file.

// Theme specific variables
$primaryColour:#939382; 
$secondaryColour:#009473;
$colorDark:#000000;
$colorLight:#f7f7f7;

// Body Font
$bodyFont: 18px;
$bodyFontMobile: 14px;

// Header
$logoWidth: 384px;

// Button
$buttonFont: $fontBody;
$buttonText: $primaryColour;
$buttonBackground: none;
$buttonHover: $colorLight;
$buttonFontSize: 18px;

//*******
// Font Family
// ******

@font-face{
	// Font faces added here 
}

// Import basic theme
@import '../main';

This should provide you with enough information to replicate the process for a site of your own. Happy Coding!