You are here

Creating a Drupal 8 Theme with Sass,Singularity & Breakpoint

In this post I wanted to share my experience of setting up a new Drupal 8 theme.

I wanted to take Drupal 8 for a spin and familiarize myself with the new TWIG template system and other theming changes, so I set out with a goal of creating a simple, clean, minimal configurations blog theme. I called it "Formata." Sounds like a cool name, right?

Demo  of the theme.

You can also Download or Clone it from GitHub

What is included in this theme:

Installing Drupal 8

You can find the latest Drupal 8 Release here or on Github

As of writing this we are at drupal 8.0-alpha8. Once you have that set up on your environment, be cautious about making upgrades and installing contrib modules (if they exist for D8). At this point Drupal 8 is in active development, so things can change and break very easily. As always, Clear Cache often and backup your Database.

Drush

I had to upgrade the Drush install in order to use it with D8. Since I am using homebrew all I had to do was: $ brew unlink drush then $ brew install --HEAD drush. Also the drush cache-clear all or drush cc all command is deprecated for Drupal 8 so instead I had to use drush cache-rebuild or the short version drush cr command.

If you are using Sublime or Textmate you might find this Twig syntax highlighting and auto-completion plugin useful.

Setting up the theme

I started looking into the D8 theme set up by reverse engineering an existing core theme. You can use Bartic or Stark (now a core theme). These themes were specifically useful and helped me better understand the new API, TWIG syntax, and different variables. There are other contrib themes that are actively being ported to Drupal 8 and have lots of good stuff in them. I've looked at adaptivetheme and gratis as an example. For more info check out D8's documentation or this post I put together earlier about D8 resources: Top Resources for Getting Started with Drupal 8

Theme directory

Your custom theme now goes into a "theme" directory in the root and not in the "/sites/all/themes" as we had gotten used to in Drupal 7.

.info file becomes theme_name.info.yml. Drupal 7's .info file was proprietary to Drupal. Now D8 has adopted the YAML format which is a standard for many programming languages. The advantage of YAML is that it uses a specific standard that's supported by other libraries.

Adding stylesheets


    # Add a CSS file:
        stylesheets:
          all:
          - css/style.css
    

You can also remove a system stylesheet. For example drupal.base.css is now replaced by normalize.css but in my theme I've removed it as I am using compass reset


      # Remove a CSS file:
        stylesheets-remove:
          - normalize.css
     

If you want to include a different version of normalize.css, you can also do an override:


        # Override a CSS file
          stylesheets-override:
          - normalize.css
     

Same with adding javascript files


        # scripts:
           - js/custom-script.js
    

Setting up regions


        regions:
           content: 'Content'
           sidebar: 'Sidebar'
           footer: 'Footer'
       
   

As you can see this is pretty straight forward, and not very different from D7.

page.html.twig

All theme files are now html.twig instead of .tpl.php. For example "page.html.twig" and variables in the template use twig syntax.


    {% if page.sidebar %}
      {{ page.sidebar }}
    {% endif %}
      
  

template.php becomes theme_name.theme

Libraries and Scripts

By default Drupal 8 doesn't load any additional scripts. So jQuery is not there, you have to declare it as a dependency. Drupal 8 now comes with Backbone.js and Underscore.js which can also be your dependencies.

drupal_add_js and drupal_add_css are deprecated so we need to use hook_library_info to declare jQuery and Modernizer as dependencies. For all core assets look into /core/assets/vendor

Here is an example of how I ended up bringing in custom javascrpt and its dependencies



  function formata_library_info() {
      // Add jquery as a dependancy on script.js
      $libraries['formata.corescripts'] = array(
        'title' => 'Adding all scripts and dependencies',
        'version' => '1.0',
        'js' => array(
         drupal_get_path('theme', 'formata') . '/js/jquery.fs.naver.min.js' => array(),
         drupal_get_path('theme', 'formata') . '/js/jquery.scrollUp.min.js' => array(),
         drupal_get_path('theme', 'formata') . '/js/rainbow/rainbow.min.js' => array(),
         drupal_get_path('theme', 'formata') . '/js/rainbow/rainbow.linenumbers.min.js' => array(),
         drupal_get_path('theme', 'formata') . '/js/rainbow/language/generic.js' => array(),
         drupal_get_path('theme', 'formata') . '/js/script.js' => array(),
        ),
        'dependencies' => array(
          array('system', 'jquery'),
          array('system', 'modernizr'),
        ),
      );
      return $libraries;
    }
    drupal_add_library('formata', 'formata.corescripts');

    

For external CDNs I used this



  function formata_css_alter(&$css) {
    $theme_path = drupal_get_path('theme', 'formata');
  // Add googlefonts.
    $googlefonts = '//fonts.googleapis.com/css?family=Merriweather:300,300italic,700,700italic,400,400italic|Merriweather+Sans:400,400italic,700,700italic,300italic,300';
    $css[$googlefonts] = array(
      'data' => $googlefonts,
      'type' => 'external',
      'every_page' => TRUE,
      'media' => 'all',
      'preprocess' => FALSE,
      'group' => CSS_AGGREGATE_THEME,
      'browsers' => array('IE' => TRUE, '!IE' => TRUE),
      'weight' => -1,
    );

     // Add FontAwesome.
    $fontawesome = '//netdna.bootstrapcdn.com/font-awesome/4.0.1/css/font-awesome.min.css';
    $css[$fontawesome] = array(
      'data' => $fontawesome,
      'type' => 'external',
      'every_page' => TRUE,
      'media' => 'all',
      'preprocess' => FALSE,
      'group' => CSS_AGGREGATE_THEME,
      'browsers' => array('IE' => TRUE, '!IE' => TRUE),
      'weight' => -2,
    );
  }

      
  

Gem file and Bundler set up

I used sass, compass, Singularity for responsive grids and Breakpoint for media queries. These gems had to be declared as dependencies in my gemfile, and Bundler takes care of the rest.

Sass Structure and Partials

This part is not necessarily Drupal 8 specific and I will not go into too much detail about it here, it just helps me keep things organized. I have to credit @Snugug and Team Sass for all the great tools they produce. This theme's structure is very similar to Drupal's Aurora which I use for all my D7 projects. I like this set up and I've adopted the structure with some modifications here:



├── partials
│   ├── design
│   │   └── _design.scss
│   ├── global
│   │   ├── _base.scss
│   │   ├── _extendables.scss
│   │   ├── _functions.scss
│   │   ├── _mixins.scss
│   │   ├── _typecsset.scss
│   │   └── _variables.scss
│   ├── layout
│   │   └── _layout.scss
│   ├── navigation
│   │   └── _navigation.scss
│   └── typography
│       └── _typography.scss
└── style.scss

All the responsive stuff is done with Singularity and Breakpoint which are great additions to my workflow.

For example if for a medium breakpoint I need my main content to span the width of 5 columns starting on the 3rd column, and 7 columns for a large breakpoint, I can declare it with these singularity's mixins:



  #main-content {
    @include breakpoint($break-medium) {
      @include grid-span(5, 3);
    }
    @include breakpoint($break-large) {
      @include grid-span(7, 3);
   }
  }

  
  

Typography and Vertical Rhythm

For Vertical Rhythm I've tried Typecsset which is a small Sass library for setting type on the web. It gives you an automatic, pixel-perfect, baseline grid.



  $typecsset-base-font-size:      16px;
  $typecsset-base-line-height:    24px;
  $typecsset-show-baseline:       true;


In conclusion

Overall, my experience with D8 theming was great. There is obviously more to learn about the new API, TWIG, and hook system, which I intend to explore as D8 gains more prominence.

Once again you can view the theme here: Demo

And Download or clone it on GitHub

SHARE SOCIAL
Senior Front End Developer
Andrei is a Senior Interactive Designer, Frond End Developer and a Drupal Themer with a passion for clean functional design and great code. He has been working with Drupal for over 6 years and has attended 3 North American DrupalCons. With a Bachelor’s degree in Interactive Design & Multimedia...→ More about Andrei
Senior Front End Developer

Andrei is a Senior Interactive Designer, Frond End Developer and a Drupal Themer with a passion for clean functional design and great code. He has been working with Drupal for over 6 years and has attended 3 North American DrupalCons. With a Bachelor’s degree in Interactive Design & Multimedia from Andrews University, USA. Andrei has traveled extensively and has lived in 3 countries prior to settling here in Canada.

Last Place Visited: (besides Vancouver) New York, Paris, Stockholm.

On the Playlist: London Grammar, Austra, The National.

Favorite Books: The Brothers Karamazov, The Meditations by Marcus Aurelius.

Movies: 2001: A Space Odyssey

Bucket list accomplishments: Biked over 7000 kms in the last 2 years. Learned how to make bread from scratch. Planted few trees. Traveled through Europe, visited Africa and lived in a country called USSR. 

 

 
Appnovation Technologies