The Drupal 8, Sass, Singularity, Breakpoint, Live Reload and Gulp logos in a row.
Calendar   11 April, 2016 //

How we got a custom Drupal 8 theme up and running with Sass, Singularity, Breakpoint, LiveReload and Gulp

#Drupal
#Frontend
#HTML, CSS & Javascript
#Tutorial
Darren Fisher, Creative Director at Pivale Drupal agency - a bearded man with dark hair and glasses.

Written by

Darren Fisher

Creative Director

Share Arrow down

Info
Did you know?
Pivale used to be known as Real Life Digital, and before that Real Life Design. This article contains references to Real Life Digital or Real Life Design which are names we traded as before becoming Pivale. You can read more about our rebrand here.
Warning
Technical disclaimer
This article is over a year old and contains technical instructions which may be out of date. The advice given may no longer be best practice.

Drupal 8 is awesome! Let's just get that right out of the way. The work that has gone in to the theme system means it is now easier than ever to spin up a custom theme and get going.

However, Drupal 8 is still in it's early days and we couldn't seem to find how to get a theme up and running with some of the open-source tools that we love to use such as sass, singularity, Breakpoint, LiveReload and Gulp. And so in true open-source spirit we decided to do the legwork and share it back with all of you lovely Drupal people.

We're going to presume you've installed Drupal 8 on your local environment otherwise we could be here all day catering to every niche environment! If you need help setting up a local environment you'll find plenty of resources online with regards to your specific operating system etc.

Just a pre-warning: this is going to a literal step by step guide to setting up a custom theme in Drupal 8. If you want a more generic overview of the Drupal 8 theme system before you get started you might want to check out my colleague Alex's fantastic article "Kickstarting with Drupal 8 themes". These instructions have been written as we've walked through the process using the Mac OSX operating system. We've tried to keep the instructions generic but some of the command line instructions may vary for Windows and Linux. Users should still be able to follow these instructions by correcting the command line instructions for your specific operating system as and when they vary.

If you want to see our working files you can find them over on our GitHub repo.

Create your custom theme info file

  1. Navigate into your “theme” directory which should be empty except for a “README.txt” file. This file contains a nice overview of what to put in this folder, but we will go into a bit more detail here. Firstly, your theme will need a name. Some people prefer to give the theme a name which doesn't relate to the project itself and others prefer to call the theme the same name as the project for consistency. We're going to go with “reallifedigital” to be consistent. You'll need to create a new directory inside of “themes” with this theme name. Now navigate into your actual theme directory once you've created it and given it a name.
  2. The first thing Drupal needs to recognise your theme is an info file. Create a new file and name it with your theme name plus the extension “.info.yml”. In our case this file will be called “reallifedigital.info.yml”. Now open this file with your preferred text editor.
  3. The file needs to be written in YAML syntax but don't panic - it's really easy. The “name:” and “description:” fields are hopefully self explanatory! The “type:” and “package:” tells Drupal what type of info file this is and where to include it within your Drupal project. The “core:” defines what version of Drupal we're working with and the “screenshot:” points to a screenshot of the theme which will appear in Drupal's UI later on once our theme is up and running. Just copy what you see below but replace the “name:” and “description:” fields with your own theme's name and description.

    name: Real Life Digital
    type: theme
    description: A red theme for the Real Life Digital website!
    package: themes
    core: 8.x
    screenshot: screenshot.jpg
  4. By default Drupal's output markup is "class-free" for total customisation. To get going quickly, though we suggest you define a “base theme”. Drupal comes with a base theme called “classy” which provides useful classes as well as other defaults. To define a base theme we simply add the following line to our info file:

    base theme: classy
  5. Next we'll need to define our libraries (for the uninitiated libraries in Drupal are simply a collection of JS/CSS as opposed to 3rd party plugins which we call modules). This will make more sense later when we set up our “libraries.yml” file but for now simply define your libraries as shown below. You'll need to replace our theme name for yours. In YAML syntax indentation is important so be sure to indent the library information and to add the “- ” before. This is how lists are defined in YAML syntax. Although for now we are only defining one library there is a good chance we will need to come back later and extend this.

    libraries:
      - reallifedigital/global
  6. Next we can define any stylesheets we want to remove. These could be stylesheets which have come Drupal's core, from our class base theme or from a contributed module. For now we're not going to remove any stylesheets but it's worth having this in your file so you can come back and remove stylesheets as and when you need to. Simply add the following line:

    stylesheets-remove:
  7. Finally, we'll define our regions. Regions are specific areas that make themselves available with Drupal's UI that we can assign content to. These come in value pairs - a machine name and a human-readable name in single quotation marks. You may have as many regions as you like and you can always come back and add more or remove some. As a general rule you'll want a header area, an area for your main content, and a footer area. That said, you may also want a specific region for menus, sidebars, copyright info etc. Here is a simple example which you can use to get going (remember indentation is critical in YAML syntax):

    regions:
      header: 'Header'
      content: 'Main Content'
      footer: 'Footer'
      copyright: 'Copyright'
    
  8. Your theme info file is now complete. Save the file and exit. We're now ready to create the libraries file. For clarity we've provided the entire info file overleaf which you can copy and paste and then customise.

    name: Real Life Digital
    type: theme
    description: A red theme for the Real Life Digital website!
    package: themes
    core: 8.x
    screenshot: screenshot.jpg
    
    base theme: classy
    
    libraries:
      - reallifedigital/global
    
    stylesheets-remove:
    
    regions:
      header: 'Header'
      content: 'Main Content'
      footer: 'Footer'
      copyright: 'Copyright'

Create your custom theme libraries file

  1. We begin by defining the global css and javascript. Remember in our info file when we defined:

    libraries:
      - reallifedigital/global

    We define the following file locations are global in our libraries file by writing:

    global:

    Simple! Then we define our global css and javascript files locations by adding the following (remember your indentation and to nest these lines below the "global" declaration:

      css:
        theme:
          css/style.css: {}
    
      js:
        js_min/scripts.js: {}
  2. We can also add dependencies such as jquery if we want to. By default jquery is turned off in Drupal but does come bundled in core. To switch it on globally add the following line below the css and javascript location declarations (ensuring indentation nests it below the "global" declaration:

      dependencies:
        - core/jquery 
  3. Your libraries info file is complete. Save and exit. Again we've included our complete libraries file below which you can copy and paste and then customise:

    global:
    
      css:
        theme:
          css/style.css: {}
    
      js:
        js_min/scripts.js: {}
    
      dependencies:
        - core/jquery
An example file structure for a Drupal 8 theme.

Create your theme directories

Now we need to set up the file structure for the theme so that we have some organisation to our workflow. Also you'll probably have noticed we defined some paths in our libraries file which don't exist yet so we'll need to create them.

  1. Create a new directory and name it “css” in lowercase. This is where your compiled css files will live. You shouldn't ever need to create any files in this folder or edit its contents manually.
  2. Create a new directory and name it “js_min” in lowercase. This is where your compiled and minified js files will live. You shouldn't ever need to create any files in this folder or edit its contents manually.
  3. Create a new directory and name it “images” in lowercase. This is where any images or icons that are theme related will live. This is not the place for images which could be considered content though.
  4. Create a new directory and name it “js” in lowercase. This is where you will write your javascript files which will be concatenated and minified by gulp before being exported into the “js_min” folder.
  5. Create a new directory and name it “sass” in lowercase. This is where you will write your stylesheets in the sass syntax which which will be compiled by gulp before being exported into the “css” folder.
  6. Create a new directory and name it “templates” in lowercase. This is where you will write your custom twig templates should you wish to override any of Drupal's default HTML output.
  7. We'll also need to give our theme a logo. Whilst you can use .jpg, .jpg, .png or .gif formats it is recommended you use the .svg format. Drupal 8 supports the .svg file extension natively and this means you can preserve your crisp vector graphics on the web. Rename your logo file to logo.svg or whatever extension you are using and drop this into your theme folder.
  8. We'll also need to give our theme a screenshot. Using your client mockups you should create a 16:9 ratio “screenshot.jpg” image and place this in your theme directory. If you fancy being really flashy you can upload an animated screenshot as a .gif file but you'll need to remember to edit your info file and change the screenshot file extension to .gif.
  9. Now we'll need to create some sub-directories in the “sass” folder. Create 4 new directories and name them as follows: “abstraction”, “base”, “components” and “variables”. You can add more stylesheet sub-directories if you wish but you'll need to remember to include them in your “style.scss” file which we will create next.
  10. Inside the “sass” folder you should now create a new file and name it “style.scss”. The purpose of this file is to import all of your sass partials so that they can be compiled into machine-readable css. We will return later to edit this file.

Set up your gulp file

  1. First, install gulp globally. To do this open the terminal (or equivalent command line tool) and type:

    sudo npm install -g gulp

    (you may need to install node.js before you can run this command).

  2. In finder, navigate to your theme folder and create a new file named “package.json”.
  3. Open “package.json” in your text editor and paste the following:

    {
      "name": "your_project_name",
      "version": "1.0.0",
      "description": "",
      "main": "gulpfile.js",
      "dependencies": {
        "browser-sync": "^2.9.3",
        "gulp": "^3.9.0",
        "gulp-autoprefixer": "^2.3.1",
        "gulp-plumber": "^1.0.1",
        "gulp-sass": "^2.0.4",
        "gulp-sourcemaps": "^1.5.2",
        "breakpoint-sass": "^2.6.1",
        "compass-mixins": "^0.12.7",
        "singularitygs": "^1.6.2",
        "gulp-watch": "^4.3.5"
      },
      "devDependencies": {
        "gulp-cssmin": "^0.1.7",
        "gulp-livereload": "^3.8.1",
        "gulp-strip-css-comments": "^1.2.0",
        "gulp-uglify": "^1.4.1",
        "gulp-uncss": "^1.0.3",
        "modularscale-sass": "^2.1.1",
        "node-sass-globbing": "0.0.23"
      },
      "scripts": {},
      "author": "",
      "license": "ISC"
    }

    Save the file.

  4. In the terminal navigate to your theme folder using the cd command. Once you are inside the theme folder enter the following command:

    npm install
  5. Return to finder and create a new file in your theme folder called “gulpfile.js”.
  6. Open “gulpfile.js” in your text editor and paste the following:

    'use strict';
    var gulp = require('gulp');
    var sass = require('gulp-sass');
    var sourcemaps = require('gulp-sourcemaps');
    var autoprefixer = require('gulp-autoprefixer');
    var importer = require('node-sass-globbing');
    var plumber = require('gulp-plumber');
    var browserSync = require('browser-sync').create();
    var cssmin = require('gulp-cssmin');
    var uncss = require('gulp-uncss');
    var stripCssComments = require('gulp-strip-css-comments');
    var uglify = require('gulp-uglify');
    var livereload = require('gulp-livereload')
    var sass_config = {
      importer: importer,
      includePaths: [
        'node_modules/breakpoint-sass/stylesheets/',
        'node_modules/singularitygs/stylesheets/',
        'node_modules/modularscale-sass/stylesheets',
        'node_modules/compass-mixins/lib/'
      ]
    };
    
    //Uglifies javascript
    gulp.task('uglify', function() {
      return gulp.src('js/*.js')
        .pipe(uglify())
        .pipe(gulp.dest('js_min'));
    });
    
    //Compiles sass
    gulp.task('sass', function () {
      gulp.src('./sass/**/*.scss')
        .pipe(plumber())
        .pipe(sourcemaps.init())
        .pipe(sass(sass_config).on('error', sass.logError))
        .pipe(autoprefixer({
          browsers: ['last 2 version']
        }))
        .pipe(stripCssComments({preserve: false}))
        .pipe(cssmin())
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest('./css'));
    });
    
    //Type "gulp" on the command line to watch file changes
    gulp.task('default', function(){
      livereload.listen();
        gulp.watch('./sass/**/*.scss', ['sass']);
        gulp.watch('./js/*.js', ['uglify']);
        gulp.watch(['./css/style.css', './**/*.twig', './js_min/*.js'], function (files){
          livereload.changed(files)
        });
    });

    Save the file.

  7. Now you need to navigate back into your theme directory and then into the “sass” directory. Remember “style.scss”? We're going to edit that now. Open this in your text editor and copy and paste the following:

    // Import external libraries.
    @import "compass";
    @import 'modular-scale';
    @import "singularitygs";
    @import "breakpoint";
    
    // Import sass partials
    @import "sass/variables/**/*.scss";
    @import "sass/abstractions/**/*.scss";
    @import "sass/base/**/*.scss";
    @import "sass/components/**/*.scss";

    What this is doing is calling the external libraries required to compile your sass and telling this file where to find the sass partials. As mentioned before if you add further directories within the “sass” directory you must call them with the @import function inside the style.scss file. You can now save the file.

The theme settings in Drupal with a newly created theme.

Enable your theme

  1. Visit to your site in the browser (yourprojectname.localhost) and click on the “Appearance” option in the top menu.
  2. Scroll to the bottom and under “Uninstalled themes” you should now see your theme. If you can't try clearing the caches under “Configuration” → “Performance”.
  3. Click the second link option which says “Install and set as default”. You should see a success message which reads: “[Your theme] is now the default theme.”
  4. Click “Back to site” which is at the top left of the screen. You should now be looking at your “unstyled” website and you're nearly ready to start theming.
  5. First, though, you'll need to click on “Structure” in the top menu, and then click on “Block layout”. You will now be on the screen where you can assign your key Drupal blocks to the regions you specified in your info.yml file. Drag and drop your branding, menu and content blocks so that they are in the regions you desire.
  6. You may notice - especially if you added custom regions - in your info.yml file that some of your content isn't displayed. This is because Drupal's standard HTML template doesn't know about your custom regions. What we need to do now is create or modify a page.html.twig file but before we do that we probably ought to set up our twig debugging and cache settings so that we can see where our twig templates are coming from.

Configure your local settings

  1. You'll need to configure your local settings in order to develop and theme quickly on your local environment. The first thing you need to do is navigate to your “www” directory in finder. From there we're now going to look inside the “sites” folder in a bit more detail.
  2. In this folder you will see a file called “example.settings.local.php”. This file is exactly what it says on the tin and should not be edited (it is an example file!) It contains all of the possible local settings you can manipulate in order to debug and develop locally. In order to alter these settings you need to create an actual local settings file. To do this copy “example.settings.local.php” and paste it into the “default” directory which is where your custom settings will live. You will likely have to enter your machine password to do this as the “sites/default” directory is protected for security reasons.
  3. Now you have done this select this file (the one inside the “default” folder) and rename it to “settings.local.php”. You will probably be asked to enter your machine password again to carry out this change.
  4. Open the newly created “settings.local.php” inside your text editor.
  5. Towards the top of this file somewhere you should see

    /**
     * Disable Dynamic Page Cache.
     *
     * Note: you should test with Dynamic Page Cache enabled, to ensure the correct
     * cacheability metadata is present (and hence the expected behavior). However,
     * in the early stages of development, you may want to disable it.
     */
     # $settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.null';

    This is Drupal's cache disable setting. To activate this setting simply remove the “#” symbol (which is “commenting out” the setting).

    Save the file and exit.

  6. Although we've just made a change to this file, Drupal won't have recognised it. This is because we need to actually switch these local settings on in our master settings file. Inside the “sites” directory you'll see the master “settings.php” file. Open this in your text editor.
  7. Scroll all the way to the bottom of this file and look for the lines:

    # if (file_exists(__DIR__ . '/settings.local.php')) {
    #   include __DIR__ . '/settings.local.php';
    # }

    This is the setting which tell Drupal to look for our “settings.local.php” and use it when we're developing locally. At the moment these three lines are preceded with the “#” symbol which means they are “commented out”. To activate this setting simply remove the “#” symbol from the start of each line so you end up with the following:

    if (file_exists(__DIR__ . '/settings.local.php')) {
      include __DIR__ . '/settings.local.php';
    }

    Save the file and exit.

  8. If you now go back to your local site in the browser and refresh you'll be met with a rather frightening error screen:

    The website encountered an unexpected error. Please try again later.
    Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "cache.backend.null". Did you mean one of these: "cache.backend.apcu", "cache.backend.php", "cache.backend.memory"? in Drupal\Component\DependencyInjection\Container->get() (line 161 of core/lib/Drupal/Component/DependencyInjection/Container.php).
    Drupal\Core\Cache\CacheFactory->get('dynamic_page_cache')
    Drupal\Core\Render\RenderCache->get(Array)
    Drupal\Core\Render\PlaceholderingRenderCache->get(Array)
    Drupal\dynamic_page_cache\EventSubscriber\DynamicPageCacheSubscriber->onRouteMatch(Object, 'kernel.request', Object)
    Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.request', Object)
    Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1)
    Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1)
    Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1)
    Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1)
    Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1)
    Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1)
    Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1)
    Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1)
    Stack\StackedHttpKernel->handle(Object, 1, 1)
    Drupal\Core\DrupalKernel->handle(Object)

    If you're not seeing this error it means that things have changed since the time of writing and you can skip this and the following step. If you are seeing this error don't panic! It's simple to fix…

  9. The error above has occurred because the PHP cache needs to be rebuilt due to the changes we've just made. To do this simply add “/rebuild.php” after your local site URL. For example, for our local site, we would type the URL: http://reallifedigital.localhost/rebuild.php. Hit enter and after a few seconds all should be well again! Alternatively, if you're using drush you can use the following command:

    drush cr
  10. Now, in finder, you can navigate back into the “sites” directory and open the “development.services.yml” file in your text editor in order to enable twig debugging so that we can locate our twig templates and begin setting up our theming regions in Drupal's HTML output. All available settings can be found in the “default.services.yml” file which is in the “sites/default” directory but for now to enable twig debugging you can simply copy the following and paste it into your “development.services.yml” file:

    parameters:
      twig.config:
        debug: true
        auto-reload: true
        cache: false

    Remember indentation is important in “.yml” files. Save the file and exit.

  11. Finally, and somewhat comically, we now need to clear the cache in order for Drupal to recognise that we've just turned off caching for twig debugging! Go to your local site in the browser and go to “Configuration” and under “DEVELOPMENT” click the “Performance” link. In here click the “Clear all caches” button.
  12. Once you've got your “Caches cleared” confirmation head back to the site by clicking the “Back to site” button in the top menu.
  13. To check twig debugging is actually working right click on the background of the site and then choose “Inspect” or “Inspect element” or whatever your browser's inspection tool is. In the markup you should now see some HTML comments which relate to your theme. These comments will tell you which twig templates Drupal is calling, where these twig templates are being called from and also what twig templates you may use in order to target HTML output more specifically.

Create a master page twig template

  1. And now at last we can write our master HTML template file to include our custom regions. You can create this file from scratch if you really want to but why reinvent the wheel? You can use your newly enabled twig debugging to find the master HTML template that Drupal is using and then copy it to your theme for editing. To do this go to your local site in the browser and then right click on the background of the site and click “Inspect” or “Inspect element” or whatever your browser's inspection tool is.
  2. In your console window scroll down past the header and Drupal toolbar markup and you should see the following:

    <!-- THEME DEBUG -->
    <!-- THEME HOOK: 'page' -->
    <!-- FILE NAME SUGGESTIONS:
       * page--front.html.twig
       * page--.html.twig
       x page.html.twig
    -->
    <!-- BEGIN OUTPUT from 'core/themes/classy/templates/layout/page.html.twig' -->

    This is the twig debug output. Under file name suggestions you can see some more specific suggestions as to how to edit the page template for the frontpage (homepage) or any other specific type of page. These suggestions are preceded by a “*” symbol showing that they are suggestions. The next options is preceded by an “x” symbol because this is the current template which Drupal is calling. As you can see this is “page.html.twig”. And below this is a very handy path to the file.

  3. In finder, navigate to this file by following the path structure shown and copy this file. Navigate back to your theme folder and inside the “templates” directory paste “page.html.twig”. Even though we have disabled the cache will will need to flush Drupal's cache every time we create a custom template in our templates folder. This is where you have to make a decision. If you only ever want custom templates to live inside your theme then you will have to live with navigating back and forth between the “class” theme directory in “core” and your own theme directory every time you want to create a new template. You will also have to flush the cache each time you do so. Alternatively, you could copy the entire “classy” “templates” directory in to your own theme and flush the cache just once. The downside to this is that all of your templates will show as overridden and you will struggle to determine whether a template has been altered from its original state. Whatever, you decide to do, make a decision and stick with it - for better or worse. And once you have, go back to your site and do the usual “Configuration” → “Performance” → “Clear all caches” routine. Then navigate “Back to site”.
  4. Now right click on the background of the site again and click “Inspect” or “Inspect element” or whatever your browser's inspection tool is. Scroll down past the header and Drupal toolbar markup until you see the page.html.twig template information. If you've been successful in overwriting Drupal's core template output you should now see:

    <!-- THEME DEBUG -->
    <!-- THEME HOOK: 'page' -->
    <!-- FILE NAME SUGGESTIONS:
       * page--front.html.twig
       * page--.html.twig
       x page.html.twig
    -->
    <!-- BEGIN OUTPUT from 'core/themes/[yourthemename]/templates/layout/page.html.twig' -->

    This means you are now calling your custom template so let's dive into editing that file.

  5. In finder, navigate to your “templates” directory inside your theme and open “page.html.twig” in your text editor. At this point if you are unfamiliar with twig you should probably check out the official twig website or for a crash course you can visit my colleague's blog: "Kickstarting with Drupal 8 themes" which covers a lot of the basics of twig templating.
  6. Now you can start editing the file. The first thing we like to do for custom templates is amend the commentary at the top of the file. You will see towards the bottom of the top block of comments there is a section which says “Regions:”. These regions are not in sync with our custom regions. Here's what we see in our twig file:

    * Regions:
     * - page.header: Items for the header region.
     * - page.highlighted: Items for the highlighted region.
     * - page.primary_menu: Items for the primary menu region.
     * - page.secondary_menu: Items for the secondary menu region.
     * - page.highlighted: Items for the highlighted content region.
     * - page.help: Dynamic help text, mostly for admin pages.
     * - page.content: The main content of the current page.
     * - page.sidebar_first: Items for the first sidebar.
     * - page.sidebar_second: Items for the second sidebar.
     * - page.footer: Items for the footer region.
     * - page.breadcrumb: Items for the breadcrumb region.

    We may have deleted some of these regions, and we also may have added some of our own custom regions so we ought to define these here so we know what regions we have available to us. If we go back to the info file we created earlier we can see all of the regions that we defined. If you've followed the exact instructions of our “info.yml” section then you'll have the following regions in your file:

    regions:
      header: 'Header'
      content: 'Main Content'
      footer: 'Footer'
      copyright: 'Copyright'

    The first three regions are already listed in the “page.html.twig” file but the copyright region is a new one we will need to stipulate. As we have removed with the remaining regions we may as well delete them from the comments to avoid confusion later on. Firstly let's delete the regions we no longer need from the comments so we're left with:

    * Regions:
     * - page.header: Items for the header region.
     * - page.content: The main content of the current page.
     * - page.footer: Items for the footer region.

    And to stipulate our new region which is the “copyright” region we simply add the following line:

    * - page.copyright: A copyright notice at the bottom of the website.

    Now whenever we look at these comments we've got an accurate idea of what regions are available to us without having to revert to looking at the “info.yml” file.

  7. Now that we've cleaned up our comments we can dive in to actually laying out the page. Start by deleting any code which is no longer applicable, and then write your new regions in by using the following syntax:

    {{ "page.[region]" }}

    This area will be heavily customised to your site but if you're looking for an example which applies to what we've done above so far then simply copy and paste the example overleaf, although you should be aware that to begin custom theming this html template needs to be written in a format that allows you achieve what it is you've agreed with your client at this stage.

  8. Once you've written your “page.html.twig” template visit your local site in the browser, refresh, and then check the markup again in the console (right-click → “Inspect” or “Inspect element” or whatever your browser's inspection tool is). You should now see your custom markup. Any block items that were previously missing from the output should now be visible if your new template file has been written correctly. Now you're ready to start theming.
  9. If you're just starting out with twig and want to see the entire twig template you can find our example file on github.
The Drupal 8, Sass, Singularity, Breakpoint, Live Reload and Gulp logos in a row.

So what is all this doing and how does it work together?

Twig + sass + singularity + breakpoint + javascript + jQuery + gulp = greatness

Here's a brief overview of what all this technology is doing:

  1. Twig is the templating system which Drupal now uses to determine the HTML output of pages, blocks, components and fields etc. It works just like regular HTML with the addition of being able inject variables from the database.
  2. Sass is syntactically awesome style sheets. Sass allows you to write CSS in a nested format, import mixins (blocks of reusable code) and specify variables to make your code more maintainable. It comes packed full of cool features. Sass is written in partials such as “_example.scss” which means you can have a separate stylesheet for every component and never have to manually specify in your <head> the locations of all the different files. The “_” denotes the file is a partial. All partials are imported, compiled and rewritten as browser readable CSS. Read more at the official sass website.
  3. Singularity is a grid framework which allows you to use an extended sass syntax to specify the location of specific components somewhere on a grid. When the sass is compiled this is then rewritten as CSS floats with the margin's correctly accounted for. Read more at the Singularity website which in turn links to the official github repo.
  4. Breakpoint is a sass extension which allows you to specify breakpoints easily for responsive design. Wrapping blocks of code in a breakpoint inclusion creates CSS media queries on compilation. Read more at the official Breakpoint GitHub.
  5. Javascript is the classic javascript you know and love/loathe! If you don't know javascript I'm not sure how you ended up here but you might want to pop over to the official website for the javascript language.
  6. jQuery is a javascript library which extends the capabilities of javascript. You can get all the documentation at the official jQuery website.
  7. Gulp is a node.js application. It's written in javascript but runs on your local machine. We can use gulp to compile our sass into css, compile and minify our javascript files. We can also write “watch” tasks in our gulpfile which watches for changes in our javascript, sass and twig files and then automatically recompiles and forces our browser to reload. To learn more visit the official gulp website.
  8. We already configured all of the above to work when we went through the process of setting up gulp apart from one small thing - the LiveReload browser extension. You can set up LiveReload extension for Chrome or for Firefox.
  9. Once LiveReload is enabled in your browser you should see an icon for it in your browser's extensions toolbar. If you click it LiveReload will fire up (but only if your gulpfile.js watch task is running). Let's run that now.
  10. Bring up the terminal and change directory into your theme folder using the command:

    cd path/to/theme

    Then type the command:

    gulp

    Hit enter. You should now see gulp start running in the console.

  11. Navigate back to the browser and activate the LiveReload extension. (If the browser isn't auto-reloading clear Drupal's caches and switch off "Aggregate CSS files" and "Aggregate JavaScript files" which are on the same page under the heading "BANDWIDTH OPTIMIZATION".)
  12. Firstly let's create a sass partial. In finder navigate to your “sass/base” directory inside your theme folder. Once in here create a new sass partial file called “_test.scss”. Open the file and write the following:

    body {
      background-color: hotpink;
    }

    Save the file.

  13. Check the terminal. You should see that gulp has just run a compile because it detected your change. If everything is working correctly when you check your browser the background of your website should have already changed to pink. The gulp task has just created a “style.css” file inside of your “css” folder in your theme based on the partial you've just written.
  14. Now we need to do the same test for our javascript. Go back to finder and navigate to your “js” directory inside your theme folder. Once in here create a new file called “scripts.js”. Open the file and write the following:

    jQuery(document).ready(function($) {
    
    })

    Save the file. Check the terminal again to see if gulp has just run a compile. If everything is working correctly then you should now see a “scripts.js” file which has been minified and saved to the “js_min” directory.

  15. Now you may go about your business writing sass partials and javascript to your heart's content whilst gulp does all the legwork of watching your files, compiling and minifying your input and reloading your browser all the while.

Conclusion

Please remember that there are an awful lot of technologies working in harmony here.

Whilst these instructions have worked without fault at the time of writing any update to any of the technologies involved could cause all of this to fall apart!

Try to test everything is working as you go so you know where the issue is occurring. Remember Google is your friend when confronted with tedious error messages!

If you need to contact me regarding anything you've read here you can do so via our contact us page.

Good luck.

Darren Fisher, Creative Director at Pivale Drupal agency - a bearded man with dark hair and glasses.

Written by

Darren Fisher

Creative Director

Darren is our creative director, responsible for our design and frontend development team as well as managing the majority of our website and multisite builds. Darren is a graduate of the University for the Creative Arts, achieving a bachelor's degree in Digital Screen Arts.

Related articles

The Pivale team from left to right - Pri Scarabelli, Julie Manning, Barry Fisher, Darren Fisher, and Daniel Johnson.

Who are Pivale?

Let's talk