Modernize Your Drupal Theme

by Dustin LeBlanc

Front-end web development is a hotbed of innovation. The Javascript world is brimming with new frameworks like Backbone, Ember, Angular, Voxel, and Three. There are a lot of exciting technologies to learn to keep our minds busy and skills sharp.

Day to day Drupal development in the real world often includes working on a lot of legacy sites. Many of these sites are still running on Drupal 6 and frequently using some legacy themes, developed before the widespread use of CSS superset frameworks like SASS and LESS.

Fear not good Drupal themer! You will not be tormented in the world of plain CSS for the rest of your days! With a little help from some RubyGems you can convert your legacy theme to use SCSS with minimal effort as I did for a project I recently inherited. I will show you how in a second; but first, here are some of the reasons I chose to invest the time and energy:

  • Coding stylesheets in one consistent format across projects helps me code faster.
  • More organized project files help me code faster.
  • The syntax of SCSS feels more like programming, which makes the transition between writing stylesheets, templates, and module files a little more seamless for me (which, you guessed it, makes me code faster :D ).
  • Modular stylesheets using includes help future developers understand the theme more easily.

The big win here is that the time invested to do the conversion will reduce the cost of all future theming work I do on the site. I am laying groundwork for future theming that inevitably needs to be done as this business is dynamically changing and there is already more theming work in the pipeline. If I knew a switch to Drupal 7 were in the immediate future I might hold off for the development of a new theme (Using Drupal Streamline to bask in all of my SCSS, Guard, and Live Reload glory).

Before we begin; make sure you have Ruby installed and are using the latest versions of RubyGems and Bundler. I personally use rbenv to manage my Ruby versions. The commands here assume a unix style terminal.

The first thing we want to do is get to our document root on the command-line:

  $ cd mysite

Once we are there (wherever "there" is for you), we need to create a Gemfile:

  $ touch Gemfile

The Gemfile is a manifest of RubyGems used in a project. We will be using two RubyGems in particular, 'sass' and 'compass'. In a future post, hopefully I can tackle retrofitting Guard and Live Reload as well.

Open the Gemfile in your favorite text editor (I prefer Sublime) and add the following:

Simple as pie. These three lines will tell Bundler where we want to get our Ruby Gems from, and then a list of the two packages we want to include; 'sass' and 'compass'.

Close up your text editor and head back to your terminal and input: $ bundle install

Your output should look something like:

Our next step is to turn our attention to our theme files. In a traditional theme, we will have our css files stored in a folder called "css". You may have multiple files stored in this folder, possibly for different outputs such as screen or print. For any files that are partials that render together, typically I combine them all down to a single legacy file. The first thing we will want to do is get into our theme's root directory, usually located somewhere like sites/all/themes/theme_name.

We want to create a new folder to hold our scss files (execute from your theme root):

  $ mkdir scss

Your folder structure may vary. For Singlebrook we typically use a folder structure that lists css, images, js, scss, templates, template.php, and our info file all at our theme root. Next we need to make a new manifest for our scss files:

  $ touch scss/style.scss

This is our master scss file that will call out our other partials. The first one I typically add is a legacy scss file that contains all of the existing css code, converted to scss. The way you include these files can vary, but the way I have done it is to concatenate them all down to one file called legacy.scss:

  $ cat file1.css file2.css file3.css >> scss/_legacy.scss

This should concatenate all of your old css into a single _legacy.scss file. Because scss is just a superset of css, you don't have to refactor this code at all; it just works. For now we are going to leave our original css files intact. Things are not fully working yet; we still have some work to do.

The above step isn't required. In my case, it simply helped to get all of the existing styles into a single file. This made a clear separation between the old files, coded in plain CSS, and any new files that I created after switching. If there is some existing logical separation in the files that would be best to maintain going forward, it may be best to simply copy each file from the css directory to the scss directory. Then rename them by including a leading underscore and converting the file extension to scss. All of this will depend on the setup of your existing theme. Some themes will include files that need to be separate.

Open your style.scss file and the first thing we need to add is our _legacy.scss partial. Notice that the file name contains an underscore at the beginning of the filename. This tells Compass that this is a partial and not to render it to a separate css file when it does our conversion later. This allows us to call this file as a partial into our manifest like so:

Notice that I have included a few other partials here too. I am bringing Compass along for the ride so that we can use any of its built-in goodness. You will notice both the _variables.scss file and the _mixins.scss file listed in this manifest as well. 

You can already see that I am beginning to break out my files into sensible partials for future development. This is one of my favorite things about SASS (besides the syntax making more sense). I can include these neatly packaged files that DRY up my other stylesheets. When handling a specific layout issue for a particular page, I don't want the stylesheet cluttered with all of our vendor prefixes for making a rounded corner or a transparent overlay. All that code gets bundled into a mixin that I then call @include to snatch into my other stylesheet. 

On to the next part of making this happen. We need a destination file for all of our scss to be output to (execute from theme root again):

$ touch css/style.css

If you already have a style.css file, you might want to rename it before creating the new file.

We now need to tell compass what our input and output files are going to be. Make sure you execute this command from your project root:

  $ compass config --css-dir path/to/your/css/directory --sass-dir path/to/your/scss/directory

This will create a config directory containing compass.rb, a Ruby file to contain our Compass configuration. You can edit that file for any custom configuration you want, including the format of the output css.

All that is left is to point Drupal at our new CSS file in the .info file of our theme:

  stylesheets[all][] = css/style.css

From our project root we can now call:

  $ compass watch

We are now using SCSS to write all of our files and letting Compass reload them for us every time we save.

Not every project has the immediate budget to upgrade an existing site to Drupal 7. Those sites will still need new features and styling as they continue to age. Just because your theme was developed without SCSS doesn't mean that you can't benefit from the recent advances in front end technology. It is easier than you might think.

I am interested in what other types of techniques folks are using to update existing sites and themes. If you have an interesting technique to share, post it in the comments below!