Drupal 8 Theming, Part One

Drupal 8

I want you to write…a theme.

Drupal is so highly customizable that developing a custom Drupal theme can be a challenging — and even daunting — undertaking.  In response to the fairly recent release of Drupal 8, we’ve decided to write a series of posts dedicated to breaking down the changes from Drupal 7 to 8 in an easy-to-follow, step-by-step, “we’re-all-in-this-together” sort of way.  We hope that you both enjoy and benefit from our research into the intricacies of Drupal 8 theming and, if you have any questions, please feel free to contact us.

With that said, kindly cue the Mortal Kombat music because:


Quick Pointers to Remember


The use of the tab key for indentation is not allowed when writing a YAML file, so you need to use spaces instead.  YAML files only require a one space indentation, but Drupal’s coding standards call for two, so definitely use two.


Every time you make a change to one of your theme files, there’s a solid chance it won’t be apparent until you’ve cleared and rebuilt your cache.  To do this, you can do one of the following:

  1. From the Admin area, go to the ‘Configuration’ page, then in the ‘Development’ section select ‘Performance’, and click the ‘Clear all caches’ button.



  1. If you’re using Drush, you can simply type ‘drush cr’, which is short for ‘drush cache-rebuild’.

Alternately (and perhaps more sensibly), rather than spending your every waking moment rebuilding your caches, it’s advisable to disable caching during development.

Moving on…

File Location

The directory structure in Drupal 8 differs a little (and in my opinion is more intuitive) than that of  Drupal 7.  Rather than placing our custom themes in the ‘sites’ directory, they will instead live in the ‘themes’ folder found in the root of Drupal 8.  But wait, there’s more!  To distinguish our custom themes from contributed themes (contrib) available for download on drupal.org, we need to create a custom folder, called ‘custom’, to house our creations.


The Info File

Name it

In Drupal 8, the ‘.info.yml’ file replaces the ‘.info’ file of Drupal 7.  The proper naming convention for the .info.yml file is ‘theme_name.info.yml’, so I’ll call mine ‘example.info.yml’.  The .info.yml file lives in the root of your custom theme folder. The name of the file needs to correspond to the name of your theme’s folder, which is why mine is named example.info.yml.  If your theme name contains spaces, use underscores to replace them.

Map it

There are four required components, or ‘mappings’, for the .info.yml file.  Mappings are simply key:value pairs that provide Drupal with the necessary info to get your theme up and running.

The required mappings are ‘name’, ‘description’, ‘type’, and ‘core’.


The value of the ‘name’ key is the human-readable name of your theme, which will appear on the Theme’s settings page.  Mine is ‘Example’.  If your theme name includes spaces, it’s the same deal as when naming your .info.yml file–just replace the spaces with underscores.


The description key is self-explanatory.  All Drupal is looking for here is a brief description of your theme that can be supplied to potential users on the ‘Appearance’ page.  My description value simply states, “An example theme for learnin’ ya.”–short and sweet.


For the ‘type’ key, Drupal just wants to know what this .info.yml file is describing.  In this case, we’re providing information about a theme, so the value for the type key is ‘theme’.  If we were describing a module, the value for type would be ‘module’ and so forth.


Core is just asking what version of the Drupal installation we’re rocking.  Since we’re hip and savvy developers, we’re using Drupal 8, and thus our ‘core’ key value should be 8.x.  Magnifique.


In addition to those four required mappings, there are a number of other mapping key:value pairs we might include to give our theme a little more depth.  Let’s discuss, shall we?

Base Theme

Setting a base theme (parent) allows your custom sub-theme (child) to inherit the base theme’s resources (styles, scripts, and templates).  For a no-frills base theme, go with Stable.  For a classier theme with more built-in styles, check out Drupal 8’s new theme ‘Classy’, which Bartik is now based off of.


Along with the name of your theme and the description you provide, the screenshot for your theme will be featured on the ‘Appearance’ page.  Best-practices dictates that you should use a screenshot of your theme; add the screenshot to your theme’s root directory, and reference it as the value of the ‘screenshot’ key.  Personally for my Example theme, I went with an illustration of some amorous cuttlefish because I enjoy a nice cephalopod.



For the ‘regions’ key, we’ve got some choices to make.  If you opt not to specify regions in your sub-theme, then Drupal’s default regions will be applied.  On the other hand, if you will be defining your own regions, technically the only one that requires specification is the ‘content’ region.

However, it is SO important to note that if you manually define any regions in your custom theme, then none of Drupal’s default regions will be applied and you’ll assume sole responsibility for declaring all of the regions you want.  In addition, you’ll need to create your own pages.html.twig file with your regions defined in order to override your base theme’s pages.html.twig template.



Another new feature of Drupal 8 is the use of libraries, which is the new standard way to include CSS and JavaScript across your Drupal site–let’s elaborate.


In the interest of making Drupal sites more performant, Drupal 8 can now use libraries to reference CSS and JavaScript that should be included across the site globally, or on a case-by-case basis.  To create CSS and JavaScript libraries for reference, we first need to author a ‘.libraries.yml’ file.  We’ll use the same naming convention that we employed for our .info.yml file, and name our file after our theme.  Hence, mine will be called ‘example.libraries.yml’.

Please note, that while libraries are an excellent option for adding CSS and JavaScript to your Drupal 8 site, they are not the only option.  You can still reference CSS and JavaScript from external URLs. This is especially useful for externally hosted libraries from content delivery networks (CDNs).

Create a library

In the libraries.yml file we’ll first choose a library name that makes sense to us (ex: global-styles).  Next, we’ll give it the distinction of being either a CSS or JavaScript file using the appropriate key.  For example, if I’m making a CSS library, I’ll choose the ‘css’ key and nest it two spaces deep under the name of my library.  Then, I’ll provide the theme key, which will be nested two spaces deep under the ‘css’ key.  Lastly, I’ll provide the path to the css file I want to include in my library followed by a colon and a set of curly braces.  The curly braces are intended to be used for adding values to the stylesheet path key, such as media queries (ex: css/print.css: { media: print } ).

In my Example theme, I’ve made my CSS and JavaScript libraries separate for the purpose of clearly demonstrating each.  However, it is perfectly acceptable to include CSS and JavaScript in the same library.


It’s important to note that when you include libraries in your .info.yml file, as we’ll be doing next, a link to the stylesheet will be added to the <head> automatically, but the css file being called will not be generated automatically.  So, to avoid any issues, you need to be sure to add that file to the specified path manually.

Referencing libraries

To make use the library we’ve just created in the .libraries.yml file, we need to reference it in the .info.yml file.  We do this by using the ‘libraries’ key, then on the next line we indent two spaces and add the name of the theme, a slash, and the name of the library, all of which is preceded by a dash.  Observe:


JavaScript files can be created and then referenced in the .libraries.yml file in much the same way that CSS libraries are, but with one addition. Drupal 8 (in an effort to improve overall performance by not loading unnecessary resources) no longer applies jQuery sitewide by default.  When we create our JavaScript libraries we need to be sure to include their dependencies in the order they are required.

When declaring JavaScript dependencies, please note that jQuery is being referenced from Drupal Core.  If I wanted to create another JavaScript library and have it reference an existing library from my theme as a dependency, then the name of the library would be preceded by the name of my theme, not ‘Core’.


Another important change to JavaScript rendering in Drupal 8 is that all JavaScript files are now loaded in the footer by default.  JavaScript should be loaded in the header only if it is critical to user interface assets.  To render JavaScript in the header, use the ‘header’ key in the asset library declaration and set the value equal to ‘true’.

Overriding Libraries

The ‘libraries-override’ key has replaced the ‘stylesheet-remove’ and ‘stylesheet-override’ keys used in previous versions of Drupal.  With it, CSS and JavaScript assets declared in libraries can be manipulated or replaced, and the library itself can actually be removed completely.


Extending Libraries

The ‘libraries-extend’ key offers a way to alter library assets by adding theme-dependent library assets when a library is attached.  This feature comes in handy when you want to style certain theme components of your site differently without having to alter your global CSS.

For a more detailed explanation of overriding and extending libraries, complete with multiple examples, check out the official Drupal 8 theming guide.

Specifying styles by page

Another feature that pertains to libraries is the preprocess functions, which was carried over from earlier versions of Drupal.  We use preprocess functions when we want to manipulate the output of a theme’s various template files.  For example, let’s say we have a JavaScript library that we only want to use on the front page of our website. Although there are a few ways to do this, one way is to employ a preprocess function. This means we need to create a new file called the ‘.theme’ file to hold our new function.

The Theme File

At this juncture, I feel like the naming convention for our new file is pretty evident, but in the interest of really driving the point home we’ll be naming our .theme file after our theme.  Kindly hold you applause as I dub mine ‘example.theme’.

In the .theme file, we’ll add this preprocess function indicating that we only want to attach our library to the front page


We then include the library for the new conditionally-applied JavaScript library in our .libraries.yml file, and reference it in the .info.yml file just as we did with the globally-applied JavaScript.


Obviously, there is a lot more that goes into fully developing a Drupal theme, but what we’ve just created is technically a theme that could be enabled on a Drupal 8 site.  I’ll be covering more topics related to Drupal 8 theming in future blog posts, so check back soon or follow Bōwst on Facebook or Twitter.  Better yet, maybe come to one of the Seacoast Drupal User Group meetings we host on the first Thursday of every month, and let’s discuss Drupal 8 theming in person.  Worst case scenario, you get free pizza and beer.

What’s the Diff?: Key Differences in Drupal 8 in a nutshell*

  • Custom theme files are now located in the ‘theme’ directory within the ‘custom’ directory, rather than the ‘sites’ directory.

  • The ‘.info.yml’ file has replaced Drupal 7’s ‘.info’ file.

  • Libraries are a new feature of Drupal 8 that are used for CSS & JavaScript implementation.

  • CSS structuring and class-naming is now based on SMACSS.

  • The Twig templating engine has replaced PHP template as the default templating engine of Drupal 7.


*I want you to know that the temptation to make a bad “No, this is Drupal in a nutshell” joke was very nearly overwhelming.  For your benefit I resisted…you’re welcome.

Click here for the next post in this series.

More Thoughts

Need help with your next digital project?

Click on that button and fill in the simple form.