This article is a quick how-to create a Bootstrap subtheme for Drupal 7, as described here and here, to be able to work with the Sass CSS preprocessor. If you don’t know what Sass is and does, read this introductory guide.

TL;DR: Sass is a CSS3 extension allowing you to use programming ‘techniques’ such as variables, nesting, inheritance and many other useful tricks (see mixins and operators for example) to simplify CSS development. Check it out. To simplify our development work, we will be using the Compass framework and Grunt task runner for automation.

Allons y! We assume you have installed Drupal 7 and Bootstrap theme in it. Hint: Most compass/grunt commands in this tutorial can also be used for Drupal 8 sub-theme development — you only need to change the first couple of commands (about renaming startekit files and variables), see here.

So, this is the first step: Copy the Sass starterkit folder (called sass) from the sites/all/themes/bootstrap/starterkits folder into sites/all/themes folder.

Rename the sass folder to a unique machine readable name. This will be your sub-theme’s “name”. For this quick tutorial, we assume you renamed it to dreaming.

Change directory into the dreaming subtheme directory.

Rename the file sass.starterkit to match the folder/theme name you have chosen above and append .info (e.g. dreaming.info):

mv sass.starterkit dreaming.info

Open that file (dreaming.info) with your favorite text editor and change the name and description of your theme (and any other properties to suite your needs). Save the file.

Using git, download the latest 3.x.x version of Bootstrap Framework Source Files from here into the your new sub-theme folder:

git clone https://github.com/twbs/bootstrap-sass.git bootstrap

This should create a sub-directory named bootstrap, so you must have a bootstrap directory inside ./subtheme.

Install node.js and ruby in your system (not covered here, sorry!). Once you do install them, install Grunt:

npm install -g grunt-cli

Next install Sass compiler and Compass:

gem install sass

gem install compass

To take advantage of all the features of the command compass stats which outputs statistics of Sass stylesheets, install css_parser as well:

gem install css_parser

Install needed Grunt plugins (we will use them in the Grunt config file, see further below). To watch your files for changes, install grunt-contrib-watch with this command:
npm install grunt-contrib-watch --save-dev

To compile your Sass files:
npm install grunt-contrib-sass --save-dev

To be able to use Compass in Grunt:
npm install grunt-contrib-compass --save-dev 

For JS minification using uglify:
npm install grunt-contrib-uglify --save-dev

To jshint your javascript:
npm install grunt-contrib-jshint --save-dev

To concat js files:
npm install grunt-contrib-concat --save-dev

To be able to run any (linux) shell command before or after running grunt tasks, install grunt-shell:
npm install grunt-shell --save-dev

Now, change directory to one step above your subtheme and write the command (changing `dreaming` to your chosen name):

compass create dreaming

This will create the necessary config files along with a default directory called sass which you can safely delete). Edit the file config.rb and change the default values compass used, i.e. css_dir and sass_dir

css_dir = “css”
sass_dir = “scss”
images_dir = “images”
javascripts_dir = “js”

In that file you may change other configurations such as preferred output style, debugging comments (that display the original location of selectors) etc. I.e. to disable comments in your final css file uncomment the line
#line_comments = false

Save the file. For reference, here’s my config.rb:

require 'compass/import-once/activate'
# Require any additional compass plugins here.
 
# Set this to the root of your project when deployed:
http_path = "/"
css_dir = "css"
sass_dir = "scss"
images_dir = "images"
javascripts_dir = "js"
 
# You can select your preferred output style here (can be overridden via the command line):
output_style = :compressed
 
# To enable relative paths to assets via compass helper functions. Uncomment:
# relative_assets = true
 
# To disable debugging comments that display the original location of your selectors. Uncomment:
line_comments = false

Now run compass from within your subtheme  folder:

compass watch

You should see

>>> Compass is watching for changes. Press Ctrl-C to Stop

This means that compass will monitor sass files in sass_dir for changes and automagically compile them to the final .css  inside css_dir.

So, open up

scss/_default-variables.scss

and change your style by adding some Sassy CSS (that’s what ‘scss’ stands for). I.e. add:

$link-color: #a90909;
$link-hover-color: darken($link-color, 15%);

Remember: SCSS syntax is  like CSS as it was designed to be a superset of CSS3’s syntax. In effect, every valid CSS3 stylesheet is also valid SCSS.

Once you save the file, compass will see the changes and compile the new style.css inside css subfolder. Note: Of course you could compile Sass files by hand using

sass scss/style.scss css/style.css

but you don’t want to do that every time you add/change any style in your SCSS files.

Grunt

Compass is ready now, but we want to be able to run various tasks automatically while developing our theme. This is why we installed Grunt packages earlier.

Now, to have Grunt monitor your SCSS/JS files and automate your development flow (for example, live-reload your site in your browser (once you’re logged) or clear drupal caches after any css/js change) create a new file called Gruntfile.js with the following code:

module.exports = function (grunt) {
    grunt.initConfig({
        watch: {
            src: {
                files: ['**/*.scss', '**/*.php'],
                tasks: ['compass:dev', 'shell:drush']
            },
            scripts: {
                files: ['./js/includes/*.js'],
                tasks: ['jshint', 'concat:js', 'uglify', 'shell:drush'],
                options: {
                    nospawn: true,
                    livereload: 45729
                }
            },
           options: {
                livereload: false,
            },
        },
        compass: {
            dev: {
                options: {
                    sassDir: 'scss',
                    cssDir: 'css',
                    imagesPath: 'images',
                    noLineComments: true,
                    outputStyle: 'compressed'
                }
            }
        },
        concat: {
            options: {separator: ';'},
            js: {
                src: ['./js/includes/*.js'],
                dest: './js/compiled.js'
            },
        },
        jshint: {
            all: ['js/src/'],
 
            options: {
                    loopfunc: true
            },
        },
       uglify: {
        options: {
          banner: '/*! dimitris kalamaras < %= grunt.template.today("yyyy-mm-dd") %> */\n'
        },
        build: {
          src: './js/compiled.js',
          dest: './js/compiled.min.js'
        }
       },
       shell: {  
          drush: {
             command: 'drush cr'
          }
       }
    });
    grunt.loadNpmTasks('grunt-contrib-compass');
    grunt.loadNpmTasks('grunt-contrib-sass');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-shell');
};

This configuration sets up a ‘watch’ task which monitors any .scss and .php files as well as any .js files in js/includes folder. It instructs Grunt to execute the tasks compass:dev, shell:drush every time you change your SASS scripts. The former task calls Compass to compile scss to css, while the latter clears drupal’s caches. Also, the config instructs Grunt to run the tasks jshint, concat:js, uglify and shell:drush every time you change any js script inside the folder js/includes. So, if there are scripts in that folder, Grunt will concatenate them and minify them to a single js/compiled.min.js file with an appropriate banner containing a timestamp (feel free to change the ‘banner: bla bla’ option to suite your needs). It’s nice, but if you don’t need that, just remove the relevant options from the Gruntfile.js.

We are ready to use Grunt. Enter:

grunt watch

Now, every time you change any scss, js (or php!) files, Grunt will compile your Sass/SCSS files into a compressed style.css (without comments), will concatenate any js files in js/includes and minify them into a single file called js/compiled.min.js. It will also run the command `drush cr` (drupal 8) after any other task, so you don’t have to do it yourself.

Isn’t that nice or what? Have fun!

Share it!
  • 2
    Shares