Drupal 8 Themeing: How to use theme libraries

Drupal 8 Themeing: How to use theme libraries

Drupal 8 is here and so is the new theming engine powered by Twig. As Drupal themers new to D8, we’ll begin to learn the new syntax and evolve to configuring our themes with .yml files. Along with these API changes, there are also new conceptual changes that, maybe, haven’t garnered the same level of attention. This article will help with the introduction and concepts of libraries in Drupal 8’s new theming layer.

Let’s build on what you (maybe) already know

In Drupal 7, many of us are familiar with the libraries folder that is placed within our /sites/all directory. Typically, this is where we would store third-party library assets such as CKEditor which is a WYSIWYG JavaScript library required for the use of the WYSIWYG Drupal contrib module. This allows us to maintain structure and organize our third-party libraries into a single folder while also alowing us to load them within the site when required. Today, with Drupal 8, themers can now do this without having to create a custom module.

THEME.info > THEME.info.yml

The following examples use Basic as the default theme. Basic is a grid based starter theme available for Drupal 7 and Drupal 8. If you were to use the examples below, you would replace the label basic with the name of your theme.

In Drupal 7, you would define all of your stylesheets and scripts in your THEME.info file as follows:

THEME.info

name = Basic
description = HTML5 and SASS theme.
core = "7.x"
project = "basic"

; Regions
regions[header] = Header
regions[content] = Content
regions[footer] = Footer

; Stylesheets
stylesheets[all][] = css/style.css
stylesheets[print][] = css/print.css

; Scripts
scripts[] = js/build/scripts.js

In Drupal 8, you now require two files, THEME.info.yml and THEME.libraries.yml, to achieve the same result

THEME.info.yml

name: Basic
description: HTML5 and SASS theme.
type: theme
core: 8.x

# Regions
regions:
  header: Header
  content: Content
  footer: Footer

# Scripts & Styles
libraries:
  - basic/global
THEME.libraries.yml
global:
  css:
    theme:
      css/style.css: {}
      css/print.css: { media: print }
  js:
    js/scripts.js: {}

Tip: While this example uses global, you can define any namespace or have multiple namespaces here.

So what is going on here? In THEME.info.yml, we define a library called global that contains our global styles. Exactly like in Drupal 7, defining this library in THEME.info.yml will ensure these assets are loaded on every page. In the THEME.libraries.yml file, we itemize the specific assets that are to be included in this library. But why?

Again, let’s take this back to the Drupal 7 concept of libraries that you may be more familiar with. The benefit of having a library is that those assets can be retrieved only when required.

Let’s say your website requires a slider on the homepage and you have decided to use a standalone custom library like bxSlider. In Drupal 7, there are two ways you could approach this:

  1. Create a custom module that would only load these bxSlider assets on the homepage. This is the ideal approach but it also has drawbacks. First, not all themers are comfortable with module development. Second, it moves the developers scope of work to module development instead of within the theme -- it’s important to maintain clarity in code structure for current and future developers.
  2. We add the bxSlider code to THEME.info and load the assets on all pages. The drawback here is that those assets are now adding weight to pages where they are not needed. While this may not have great performance implications with one lightweight library, this does not scale when leveraging multiple libraries.

Drupal 8 libraries now gives us the best of both worlds. As themers we can configure libraries without diving into custom module development. We have the ability to load assets as required, while also keeping our code contained in our decoupled theme.

THEME.info.yml

name: Basic
description: HTML5 and SASS theme.
type: theme
core: 8.x

# Regions
regions:
  header: Header
  content: Content
  footer: Footer

# Scripts & Styles
libraries:
  - basic/global

THEME.libraries.yml

global: 
  css: 
    theme: 
      css/style.css: {} 
    css/print.css: { media: print } 
  js:
    js/scripts.js: {} 
bxslider: 
  css: 
    theme: 
      css/bxslider.css: {} 
  js: 
    js/bxslider.js: {} 
  dependencies:
    - core/jquery

The above example includes a new library defined as bxslider. We have bundled the CSS and JS files that will be required within this library. You will also noticed we have called a core/jquery dependency. In the same vain as theme libraries, JQuery will only be loaded on pages that require it. This is new to Drupal 8. Because bxslider does require JQuery, we need to define that dependency so that Drupal is aware it needs to be loaded.

Take note that we have not defined the bxslider library in THEME.info.yml. If we were to do this, like in Drupal 7, it would load the assets to all pages. Which leads us to the next step, defining when the library will be included on pages.

views-view--view_name.html.twig

{{ attach_library('THEME/bxslider') }}

Read more about views Twig templates

We simply add this code snippet referencing our library to our Twig template and, voila!, our bxslider library will be included only when this template is called. The code that loads the library, sits right alongside the code the powers the display. A great improvement for code clarity, componentization and best practices.

Want more?

Read on to learn more about Drupal 8 Themeing with Defining your file organization with SMACSS

Sign up for our weekly newsletter to receive free resources on eCommerce and technology.